in core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java [4077:4284]
public final BigDecimal readBigDecimal() {
boolean valid = false;
final char[] chars = this.chars;
char ch = this.ch;
int offset = this.offset;
boolean value = false;
BigDecimal decimal = null;
int quote = '\0';
if (ch == '"' || ch == '\'') {
quote = ch;
ch = chars[offset++];
if (ch == quote) {
this.ch = offset == end ? EOI : chars[offset++];
this.offset = offset;
nextIfComma();
return null;
}
}
final int start = offset;
if (ch == '-') {
negative = true;
ch = chars[offset++];
} else {
negative = false;
if (ch == '+') {
ch = chars[offset++];
}
}
valueType = JSON_TYPE_INT;
boolean overflow = false;
long longValue = 0;
while (ch >= '0' && ch <= '9') {
valid = true;
if (!overflow) {
long r = longValue * 10;
if ((longValue | 10) >>> 31 == 0L || (r / 10 == longValue)) {
longValue = r + (ch - '0');
} else {
overflow = true;
}
}
if (offset == end) {
ch = EOI;
offset++;
break;
}
ch = chars[offset++];
}
if (longValue < 0) {
overflow = true;
}
this.scale = 0;
if (ch == '.') {
valueType = JSON_TYPE_DEC;
ch = chars[offset++];
while (ch >= '0' && ch <= '9') {
valid = true;
this.scale++;
if (!overflow) {
long r = longValue * 10;
if ((longValue | 10) >>> 31 == 0L || (r / 10 == longValue)) {
longValue = r + (ch - '0');
} else {
overflow = true;
}
}
if (offset == end) {
ch = EOI;
offset++;
break;
}
ch = chars[offset++];
}
}
int expValue = 0;
if (ch == 'e' || ch == 'E') {
boolean negativeExp;
ch = chars[offset++];
if ((negativeExp = ch == '-') || ch == '+') {
ch = chars[offset++];
}
while (ch >= '0' && ch <= '9') {
valid = true;
int byteVal = (ch - '0');
expValue = expValue * 10 + byteVal;
if (expValue > MAX_EXP) {
throw new JSONException("too large exp value : " + expValue);
}
if (offset == end) {
ch = EOI;
offset++;
break;
}
ch = chars[offset++];
}
if (negativeExp) {
expValue = -expValue;
}
this.exponent = (short) expValue;
valueType = JSON_TYPE_DEC;
}
if (offset == start) {
if (ch == 'n' && chars[offset++] == 'u' && chars[offset++] == 'l' && chars[offset++] == 'l') {
if ((context.features & Feature.ErrorOnNullForPrimitives.mask) != 0) {
throw new JSONException(info("long value not support input null"));
}
wasNull = true;
value = true;
ch = offset == end ? EOI : chars[offset];
offset++;
valid = true;
} else if (ch == 't' && offset + 3 <= end && chars[offset] == 'r' && chars[offset + 1] == 'u' && chars[offset + 2] == 'e') {
valid = true;
offset += 3;
value = true;
decimal = BigDecimal.ONE;
ch = offset == end ? EOI : chars[offset];
offset++;
} else if (ch == 'f' && offset + 4 <= end
&& chars[offset] == 'a'
&& chars[offset + 1] == 'l'
&& chars[offset + 2] == 's'
&& chars[offset + 3] == 'e') {
valid = true;
offset += 4;
decimal = BigDecimal.ZERO;
value = true;
ch = offset == end ? EOI : chars[offset];
offset++;
} else if (ch == '{' && quote == 0) {
JSONObject jsonObject = new JSONObject();
readObject(jsonObject, 0);
wasNull = false;
return decimal(jsonObject);
} else if (ch == '[' && quote == 0) {
List array = readArray();
if (!array.isEmpty()) {
throw new JSONException(info());
}
wasNull = true;
return null;
}
}
int len = offset - start;
if (quote != 0) {
if (ch != quote) {
String str = readString();
try {
return TypeUtils.toBigDecimal(str);
} catch (NumberFormatException e) {
throw new JSONException(info("cast to decimal error " + str), e);
}
} else {
ch = offset >= end ? EOI : chars[offset++];
}
}
if (!value) {
if (expValue == 0 && !overflow && longValue != 0) {
decimal = BigDecimal.valueOf(negative ? -longValue : longValue, scale);
value = true;
}
if (!value) {
decimal = TypeUtils.parseBigDecimal(chars, start - 1, len);
}
if (ch == 'L' || ch == 'F' || ch == 'D' || ch == 'B' || ch == 'S') {
ch = offset >= end ? EOI : chars[offset++];
}
}
while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
ch = offset == end ? EOI : chars[offset++];
}
if (comma = (ch == ',')) {
// next inline
ch = offset == end ? EOI : chars[offset++];
while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
ch = offset == end ? EOI : chars[offset++];
}
}
if (!valid) {
throw new JSONException(info("illegal input error"));
}
this.ch = ch;
this.offset = offset;
return decimal;
}