@@ -254,6 +254,16 @@ public class CsvDecoder
254
254
255
255
protected BigDecimal _numberBigDecimal ;
256
256
257
+ /**
258
+ * Textual number representation captured from input in cases lazy-parsing
259
+ * is desired.
260
+ *<p>
261
+ * As of 2.14, this only applies to {@link BigInteger} and {@link BigDecimal}.
262
+ *
263
+ * @since 2.14
264
+ */
265
+ protected String _numberString ;
266
+
257
267
/*
258
268
/**********************************************************************
259
269
/* Life-cycle
@@ -1019,12 +1029,12 @@ public Number getNumberValue(boolean exact) throws IOException
1019
1029
return Long .valueOf (_numberLong );
1020
1030
}
1021
1031
if ((_numTypesValid & NR_BIGINT ) != 0 ) {
1022
- return _numberBigInt ;
1032
+ return _getBigInteger () ;
1023
1033
}
1024
1034
// And then floating point types. But here optimal type
1025
1035
// needs to be big decimal, to avoid losing any data?
1026
1036
if ((_numTypesValid & NR_BIGDECIMAL ) != 0 ) {
1027
- return _numberBigDecimal ;
1037
+ return _getBigDecimal () ;
1028
1038
}
1029
1039
if ((_numTypesValid & NR_DOUBLE ) == 0 ) { // sanity check
1030
1040
_throwInternal ();
@@ -1093,7 +1103,7 @@ public BigInteger getBigIntegerValue() throws IOException
1093
1103
convertNumberToBigInteger ();
1094
1104
}
1095
1105
}
1096
- return _numberBigInt ;
1106
+ return _getBigInteger () ;
1097
1107
}
1098
1108
1099
1109
public float getFloatValue () throws IOException
@@ -1126,6 +1136,40 @@ public BigDecimal getDecimalValue() throws IOException
1126
1136
convertNumberToBigDecimal ();
1127
1137
}
1128
1138
}
1139
+ return _getBigDecimal ();
1140
+ }
1141
+
1142
+ /**
1143
+ * Internal accessor that needs to be used for accessing number value of type
1144
+ * {@link BigInteger} which -- as of 2.14 -- is typically lazily parsed.
1145
+ *
1146
+ * @since 2.14
1147
+ */
1148
+ protected BigInteger _getBigInteger () {
1149
+ if (_numberBigInt != null ) {
1150
+ return _numberBigInt ;
1151
+ } else if (_numberString == null ) {
1152
+ throw new IllegalStateException ("cannot get BigInteger from current parser state" );
1153
+ }
1154
+ _numberBigInt = NumberInput .parseBigInteger (_numberString );
1155
+ _numberString = null ;
1156
+ return _numberBigInt ;
1157
+ }
1158
+
1159
+ /**
1160
+ * Internal accessor that needs to be used for accessing number value of type
1161
+ * {@link BigDecimal} which -- as of 2.14 -- is typically lazily parsed.
1162
+ *
1163
+ * @since 2.14
1164
+ */
1165
+ protected BigDecimal _getBigDecimal () {
1166
+ if (_numberBigDecimal != null ) {
1167
+ return _numberBigDecimal ;
1168
+ } else if (_numberString == null ) {
1169
+ throw new IllegalStateException ("cannot get BigDecimal from current parser state" );
1170
+ }
1171
+ _numberBigDecimal = NumberInput .parseBigDecimal (_numberString );
1172
+ _numberString = null ;
1129
1173
return _numberBigDecimal ;
1130
1174
}
1131
1175
@@ -1226,7 +1270,8 @@ private final void _parseSlowFloatValue(boolean exactNumber)
1226
1270
*/
1227
1271
try {
1228
1272
if (exactNumber ) {
1229
- _numberBigDecimal = _textBuffer .contentsAsDecimal ();
1273
+ _numberBigDecimal = null ;
1274
+ _numberString = _textBuffer .contentsAsString ();
1230
1275
_numTypesValid = NR_BIGDECIMAL ;
1231
1276
} else {
1232
1277
// Otherwise double has to do
@@ -1251,7 +1296,8 @@ private final void _parseSlowIntValue(char[] buf, int offset, int len,
1251
1296
_numTypesValid = NR_LONG ;
1252
1297
} else {
1253
1298
// nope, need the heavy guns... (rare case)
1254
- _numberBigInt = NumberInput .parseBigInteger (numStr );
1299
+ _numberBigInt = null ;
1300
+ _numberString = numStr ;
1255
1301
_numTypesValid = NR_BIGINT ;
1256
1302
}
1257
1303
} catch (NumberFormatException nex ) {
@@ -1278,19 +1324,20 @@ protected void convertNumberToInt() throws IOException
1278
1324
_numberInt = result ;
1279
1325
} else if ((_numTypesValid & NR_BIGINT ) != 0 ) {
1280
1326
// !!! Should check for range...
1281
- _numberInt = _numberBigInt .intValue ();
1327
+ _numberInt = _getBigInteger () .intValue ();
1282
1328
} else if ((_numTypesValid & NR_DOUBLE ) != 0 ) {
1283
1329
// Need to check boundaries
1284
1330
if (_numberDouble < MIN_INT_D || _numberDouble > MAX_INT_D ) {
1285
1331
reportOverflowInt ();
1286
1332
}
1287
1333
_numberInt = (int ) _numberDouble ;
1288
1334
} else if ((_numTypesValid & NR_BIGDECIMAL ) != 0 ) {
1289
- if (BD_MIN_INT .compareTo (_numberBigDecimal ) > 0
1290
- || BD_MAX_INT .compareTo (_numberBigDecimal ) < 0 ) {
1335
+ final BigDecimal bigDecimal = _getBigDecimal ();
1336
+ if (BD_MIN_INT .compareTo (bigDecimal ) > 0
1337
+ || BD_MAX_INT .compareTo (bigDecimal ) < 0 ) {
1291
1338
reportOverflowInt ();
1292
1339
}
1293
- _numberInt = _numberBigDecimal .intValue ();
1340
+ _numberInt = bigDecimal .intValue ();
1294
1341
} else {
1295
1342
_throwInternal (); // should never get here
1296
1343
}
@@ -1304,19 +1351,20 @@ protected void convertNumberToLong() throws IOException
1304
1351
_numberLong = _numberInt ;
1305
1352
} else if ((_numTypesValid & NR_BIGINT ) != 0 ) {
1306
1353
// !!! Should check for range...
1307
- _numberLong = _numberBigInt .longValue ();
1354
+ _numberLong = _getBigInteger () .longValue ();
1308
1355
} else if ((_numTypesValid & NR_DOUBLE ) != 0 ) {
1309
1356
// Need to check boundaries
1310
1357
if (_numberDouble < MIN_LONG_D || _numberDouble > MAX_LONG_D ) {
1311
1358
reportOverflowLong ();
1312
1359
}
1313
1360
_numberLong = (long ) _numberDouble ;
1314
1361
} else if ((_numTypesValid & NR_BIGDECIMAL ) != 0 ) {
1315
- if (BD_MIN_LONG .compareTo (_numberBigDecimal ) > 0
1316
- || BD_MAX_LONG .compareTo (_numberBigDecimal ) < 0 ) {
1362
+ final BigDecimal bigDecimal = _getBigDecimal ();
1363
+ if (BD_MIN_LONG .compareTo (bigDecimal ) > 0
1364
+ || BD_MAX_LONG .compareTo (bigDecimal ) < 0 ) {
1317
1365
reportOverflowLong ();
1318
1366
}
1319
- _numberLong = _numberBigDecimal .longValue ();
1367
+ _numberLong = bigDecimal .longValue ();
1320
1368
} else {
1321
1369
_throwInternal (); // should never get here
1322
1370
}
@@ -1329,7 +1377,7 @@ protected void convertNumberToBigInteger()
1329
1377
{
1330
1378
if ((_numTypesValid & NR_BIGDECIMAL ) != 0 ) {
1331
1379
// here it'll just get truncated, no exceptions thrown
1332
- _numberBigInt = _numberBigDecimal .toBigInteger ();
1380
+ _numberBigInt = _getBigDecimal () .toBigInteger ();
1333
1381
} else if ((_numTypesValid & NR_LONG ) != 0 ) {
1334
1382
_numberBigInt = BigInteger .valueOf (_numberLong );
1335
1383
} else if ((_numTypesValid & NR_INT ) != 0 ) {
@@ -1352,9 +1400,9 @@ protected void convertNumberToDouble()
1352
1400
*/
1353
1401
1354
1402
if ((_numTypesValid & NR_BIGDECIMAL ) != 0 ) {
1355
- _numberDouble = _numberBigDecimal .doubleValue ();
1403
+ _numberDouble = _getBigDecimal () .doubleValue ();
1356
1404
} else if ((_numTypesValid & NR_BIGINT ) != 0 ) {
1357
- _numberDouble = _numberBigInt .doubleValue ();
1405
+ _numberDouble = _getBigInteger () .doubleValue ();
1358
1406
} else if ((_numTypesValid & NR_LONG ) != 0 ) {
1359
1407
_numberDouble = _numberLong ;
1360
1408
} else if ((_numTypesValid & NR_INT ) != 0 ) {
@@ -1374,7 +1422,7 @@ protected void convertNumberToBigDecimal() throws IOException
1374
1422
*/
1375
1423
_numberBigDecimal = NumberInput .parseBigDecimal (getText ());
1376
1424
} else if ((_numTypesValid & NR_BIGINT ) != 0 ) {
1377
- _numberBigDecimal = new BigDecimal (_numberBigInt );
1425
+ _numberBigDecimal = new BigDecimal (_getBigInteger () );
1378
1426
} else if ((_numTypesValid & NR_LONG ) != 0 ) {
1379
1427
_numberBigDecimal = BigDecimal .valueOf (_numberLong );
1380
1428
} else if ((_numTypesValid & NR_INT ) != 0 ) {
0 commit comments