Skip to content

Commit f23661f

Browse files
committed
fix int range
1 parent e8a5956 commit f23661f

File tree

2 files changed

+59
-14
lines changed

2 files changed

+59
-14
lines changed

src/main/java/com/jsoniter/IterImplNumber.java

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ class IterImplNumber {
4343
private final static int DOT_IN_NUMBER = -3;
4444
private final static int INVALID_CHAR_FOR_NUMBER = -1;
4545
private static final int POW10[] = {1, 10, 100, 1000, 10000, 100000, 1000000};
46-
private final static long LONG_SAFE_TO_MULTIPLY_10 = (Long.MAX_VALUE / 10) - 10;
47-
private final static int INT_SAFE_TO_MULTIPLY_10 = (Integer.MAX_VALUE / 10) - 10;
46+
private final static long LONG_SAFE_TO_MULTIPLY_10 = (Long.MAX_VALUE / 10) - 1;
47+
private final static int INT_SAFE_TO_MULTIPLY_10 = (Integer.MAX_VALUE / 10) - 1;
4848

4949
static {
5050
for (int i = 0; i < digits.length; i++) {
@@ -247,34 +247,74 @@ public static final String readNumber(final JsonIterator iter) throws IOExceptio
247247
public static final int readInt(final JsonIterator iter) throws IOException {
248248
byte c = IterImpl.nextToken(iter);
249249
if (c == '-') {
250-
return -readUnsignedInt(iter, IterImpl.readByte(iter));
250+
return readNegativeInt(iter);
251251
} else {
252-
return readUnsignedInt(iter, c);
252+
return readPositiveInt(iter, c);
253253
}
254254
}
255255

256-
public static final int readUnsignedInt(final JsonIterator iter, byte c) throws IOException {
257-
int result = intDigits[c];
258-
if (result == 0) {
256+
public static final int readPositiveInt(final JsonIterator iter, byte c) throws IOException {
257+
int value = intDigits[c];
258+
if (value == 0) {
259259
return 0;
260260
}
261-
if (result == INVALID_CHAR_FOR_NUMBER) {
262-
throw iter.reportError("readUnsignedInt", "expect 0~9");
261+
if (value == INVALID_CHAR_FOR_NUMBER) {
262+
throw iter.reportError("readPositiveInt", "expect 0~9");
263263
}
264264
for (;;) {
265265
for (int i = iter.head; i < iter.tail; i++) {
266266
int ind = intDigits[iter.buf[i]];
267267
if (ind == INVALID_CHAR_FOR_NUMBER) {
268268
iter.head = i;
269-
return result;
269+
return value;
270+
}
271+
if (value > INT_SAFE_TO_MULTIPLY_10) {
272+
int value2 = (value << 3) + (value << 1) + ind;
273+
if (value2 < INT_SAFE_TO_MULTIPLY_10 * 10) {
274+
throw iter.reportError("readPositiveInt", "value is too large for int");
275+
} else {
276+
value = value2;
277+
continue;
278+
}
279+
}
280+
value = (value << 3) + (value << 1) + ind;
281+
}
282+
if (!IterImpl.loadMore(iter)) {
283+
return value;
284+
}
285+
}
286+
}
287+
288+
public static final int readNegativeInt(final JsonIterator iter) throws IOException {
289+
byte c = IterImpl.readByte(iter);
290+
int ind = intDigits[c];
291+
if (ind == 0) {
292+
return 0;
293+
}
294+
if (ind == INVALID_CHAR_FOR_NUMBER) {
295+
throw iter.reportError("readNegativeInt", "expect 0~9");
296+
}
297+
int value = -ind;
298+
for (;;) {
299+
for (int i = iter.head; i < iter.tail; i++) {
300+
ind = intDigits[iter.buf[i]];
301+
if (ind == INVALID_CHAR_FOR_NUMBER) {
302+
iter.head = i;
303+
return value;
270304
}
271-
if (result > INT_SAFE_TO_MULTIPLY_10) {
272-
throw iter.reportError("readUnsignedInt", "value is too large for int");
305+
if (value > INT_SAFE_TO_MULTIPLY_10) {
306+
int value2 = (value << 3) + (value << 1) - ind;
307+
if (value2 < INT_SAFE_TO_MULTIPLY_10 * 10) {
308+
throw iter.reportError("readNegativeInt", "value is too large for int");
309+
} else {
310+
value = value2;
311+
continue;
312+
}
273313
}
274-
result = (result << 3) + (result << 1) + ind;
314+
value = (value << 3) + (value << 1) - ind;
275315
}
276316
if (!IterImpl.loadMore(iter)) {
277-
return result;
317+
return value;
278318
}
279319
}
280320
}

src/test/java/com/jsoniter/TestInteger.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ public void test_positive_negative() throws IOException {
1616
assertEquals(-4321, parseInt("-4321"));
1717
}
1818

19+
public void test_max_min_int() throws IOException {
20+
assertEquals(Integer.MAX_VALUE, parseInt(Integer.toString(Integer.MAX_VALUE)));
21+
assertEquals(Integer.MIN_VALUE, parseInt(Integer.toString(Integer.MIN_VALUE)));
22+
}
23+
1924
public void test_large_number() throws IOException {
2025
try {
2126
parseInt("123456789123456789");

0 commit comments

Comments
 (0)