Skip to content

Commit 40ca712

Browse files
committed
Merge branch 'plokhotnyuk-master'
2 parents f5dfab1 + bf47ad2 commit 40ca712

File tree

5 files changed

+104
-59
lines changed

5 files changed

+104
-59
lines changed

src/main/java/com/jsoniter/IterImpl.java

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -323,123 +323,135 @@ public static int updateStringCopyBound(final JsonIterator iter, final int bound
323323
return bound;
324324
}
325325

326-
static final int readPositiveInt(final JsonIterator iter, byte c) throws IOException {
326+
static final int readInt(final JsonIterator iter, final byte c) throws IOException {
327327
int ind = IterImplNumber.intDigits[c];
328328
if (ind == 0) {
329329
IterImplForStreaming.assertNotLeadingZero(iter);
330330
return 0;
331331
}
332332
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
333-
throw iter.reportError("readPositiveInt", "expect 0~9");
333+
throw iter.reportError("readInt", "expect 0~9");
334334
}
335335
if (iter.tail - iter.head > 9) {
336336
int i = iter.head;
337337
int ind2 = IterImplNumber.intDigits[iter.buf[i]];
338338
if (ind2 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
339339
iter.head = i;
340-
return ind;
340+
return -ind;
341341
}
342342
int ind3 = IterImplNumber.intDigits[iter.buf[++i]];
343343
if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
344344
iter.head = i;
345-
return ind * 10 + ind2;
345+
ind = ind * 10 + ind2;
346+
return -ind;
346347
}
347348
int ind4 = IterImplNumber.intDigits[iter.buf[++i]];
348349
if (ind4 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
349350
iter.head = i;
350-
return ind * 100 + ind2 * 10 + ind3;
351+
ind = ind * 100 + ind2 * 10 + ind3;
352+
return -ind;
351353
}
352354
int ind5 = IterImplNumber.intDigits[iter.buf[++i]];
353355
if (ind5 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
354356
iter.head = i;
355-
return ind * 1000 + ind2 * 100 + ind3 * 10 + ind4;
357+
ind = ind * 1000 + ind2 * 100 + ind3 * 10 + ind4;
358+
return -ind;
356359
}
357360
int ind6 = IterImplNumber.intDigits[iter.buf[++i]];
358361
if (ind6 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
359362
iter.head = i;
360-
return ind * 10000 + ind2 * 1000 + ind3 * 100 + ind4 * 10 + ind5;
363+
ind = ind * 10000 + ind2 * 1000 + ind3 * 100 + ind4 * 10 + ind5;
364+
return -ind;
361365
}
362366
int ind7 = IterImplNumber.intDigits[iter.buf[++i]];
363367
if (ind7 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
364368
iter.head = i;
365-
return ind * 100000 + ind2 * 10000 + ind3 * 1000 + ind4 * 100 + ind5 * 10 + ind6;
369+
ind = ind * 100000 + ind2 * 10000 + ind3 * 1000 + ind4 * 100 + ind5 * 10 + ind6;
370+
return -ind;
366371
}
367372
int ind8 = IterImplNumber.intDigits[iter.buf[++i]];
368373
if (ind8 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
369374
iter.head = i;
370-
return ind * 1000000 + ind2 * 100000 + ind3 * 10000 + ind4 * 1000 + ind5 * 100 + ind6 * 10 + ind7;
375+
ind = ind * 1000000 + ind2 * 100000 + ind3 * 10000 + ind4 * 1000 + ind5 * 100 + ind6 * 10 + ind7;
376+
return -ind;
371377
}
372378
int ind9 = IterImplNumber.intDigits[iter.buf[++i]];
373379
ind = ind * 10000000 + ind2 * 1000000 + ind3 * 100000 + ind4 * 10000 + ind5 * 1000 + ind6 * 100 + ind7 * 10 + ind8;
374380
iter.head = i;
375381
if (ind9 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
376-
return ind;
382+
return -ind;
377383
}
378384
}
379385
return IterImplForStreaming.readIntSlowPath(iter, ind);
380386
}
381387

382-
static final long readPositiveLong(final JsonIterator iter, byte c) throws IOException {
388+
static final long readLong(final JsonIterator iter, final byte c) throws IOException {
383389
long ind = IterImplNumber.intDigits[c];
384390
if (ind == 0) {
385391
IterImplForStreaming.assertNotLeadingZero(iter);
386392
return 0;
387393
}
388394
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
389-
throw iter.reportError("readPositiveLong", "expect 0~9");
395+
throw iter.reportError("readLong", "expect 0~9");
390396
}
391397
if (iter.tail - iter.head > 9) {
392398
int i = iter.head;
393399
int ind2 = IterImplNumber.intDigits[iter.buf[i]];
394400
if (ind2 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
395401
iter.head = i;
396-
return ind;
402+
return -ind;
397403
}
398404
int ind3 = IterImplNumber.intDigits[iter.buf[++i]];
399405
if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
400406
iter.head = i;
401-
return ind * 10 + ind2;
407+
ind = ind * 10 + ind2;
408+
return -ind;
402409
}
403410
int ind4 = IterImplNumber.intDigits[iter.buf[++i]];
404411
if (ind4 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
405412
iter.head = i;
406-
return ind * 100 + ind2 * 10 + ind3;
413+
ind = ind * 100 + ind2 * 10 + ind3;
414+
return -ind;
407415
}
408416
int ind5 = IterImplNumber.intDigits[iter.buf[++i]];
409417
if (ind5 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
410418
iter.head = i;
411-
return ind * 1000 + ind2 * 100 + ind3 * 10 + ind4;
419+
ind = ind * 1000 + ind2 * 100 + ind3 * 10 + ind4;
420+
return -ind;
412421
}
413422
int ind6 = IterImplNumber.intDigits[iter.buf[++i]];
414423
if (ind6 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
415424
iter.head = i;
416-
return ind * 10000 + ind2 * 1000 + ind3 * 100 + ind4 * 10 + ind5;
425+
ind = ind * 10000 + ind2 * 1000 + ind3 * 100 + ind4 * 10 + ind5;
426+
return -ind;
417427
}
418428
int ind7 = IterImplNumber.intDigits[iter.buf[++i]];
419429
if (ind7 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
420430
iter.head = i;
421-
return ind * 100000 + ind2 * 10000 + ind3 * 1000 + ind4 * 100 + ind5 * 10 + ind6;
431+
ind = ind * 100000 + ind2 * 10000 + ind3 * 1000 + ind4 * 100 + ind5 * 10 + ind6;
432+
return -ind;
422433
}
423434
int ind8 = IterImplNumber.intDigits[iter.buf[++i]];
424435
if (ind8 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
425436
iter.head = i;
426-
return ind * 1000000 + ind2 * 100000 + ind3 * 10000 + ind4 * 1000 + ind5 * 100 + ind6 * 10 + ind7;
437+
ind = ind * 1000000 + ind2 * 100000 + ind3 * 10000 + ind4 * 1000 + ind5 * 100 + ind6 * 10 + ind7;
438+
return -ind;
427439
}
428440
int ind9 = IterImplNumber.intDigits[iter.buf[++i]];
429441
ind = ind * 10000000 + ind2 * 1000000 + ind3 * 100000 + ind4 * 10000 + ind5 * 1000 + ind6 * 100 + ind7 * 10 + ind8;
430442
iter.head = i;
431443
if (ind9 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
432-
return ind;
444+
return -ind;
433445
}
434446
}
435447
return IterImplForStreaming.readLongSlowPath(iter, ind);
436448
}
437449

438-
static final double readPositiveDouble(final JsonIterator iter) throws IOException {
450+
static final double readDouble(final JsonIterator iter) throws IOException {
439451
int oldHead = iter.head;
440452
try {
441453
try {
442-
long value = IterImplNumber.readLong(iter); // without the dot
454+
long value = IterImplNumber.readLong(iter); // without the dot & sign
443455
if (iter.head == iter.tail) {
444456
return value;
445457
}
@@ -448,11 +460,14 @@ static final double readPositiveDouble(final JsonIterator iter) throws IOExcepti
448460
iter.head++;
449461
int start = iter.head;
450462
c = iter.buf[iter.head++];
451-
long decimalPart = readPositiveLong(iter, c);
463+
long decimalPart = readLong(iter, c);
464+
if (decimalPart == Long.MIN_VALUE) {
465+
return IterImplForStreaming.readDoubleSlowPath(iter);
466+
}
467+
decimalPart = -decimalPart;
452468
int decimalPlaces = iter.head - start;
453469
if (decimalPlaces > 0 && decimalPlaces < IterImplNumber.POW10.length && (iter.head - oldHead) < 10) {
454-
value = value * IterImplNumber.POW10[decimalPlaces] + decimalPart;
455-
return value / (double) IterImplNumber.POW10[decimalPlaces];
470+
return value + (decimalPart / (double) IterImplNumber.POW10[decimalPlaces]);
456471
} else {
457472
iter.head = oldHead;
458473
return IterImplForStreaming.readDoubleSlowPath(iter);

src/main/java/com/jsoniter/IterImplForStreaming.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -487,19 +487,21 @@ public final static int readStringSlowPath(JsonIterator iter, int j) throws IOEx
487487
}
488488
}
489489

490-
static long readLongSlowPath(JsonIterator iter, long value) throws IOException {
490+
static long readLongSlowPath(final JsonIterator iter, long value) throws IOException {
491+
value = -value; // add negatives to avoid redundant checks for Long.MIN_VALUE on each iteration
492+
long multmin = -922337203685477580L; // limit / 10
491493
for (; ; ) {
492494
for (int i = iter.head; i < iter.tail; i++) {
493495
int ind = IterImplNumber.intDigits[iter.buf[i]];
494496
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
495497
iter.head = i;
496498
return value;
497499
}
498-
if (value == Long.MIN_VALUE) {
500+
if (value < multmin) {
499501
throw iter.reportError("readLongSlowPath", "value is too large for long");
500502
}
501-
value = (value << 3) + (value << 1) + ind;
502-
if (value < 0 && value != Long.MIN_VALUE) {
503+
value = (value << 3) + (value << 1) - ind;
504+
if (value >= 0) {
503505
throw iter.reportError("readLongSlowPath", "value is too large for long");
504506
}
505507
}
@@ -510,19 +512,21 @@ static long readLongSlowPath(JsonIterator iter, long value) throws IOException {
510512
}
511513
}
512514

513-
static int readIntSlowPath(JsonIterator iter, int value) throws IOException {
515+
static int readIntSlowPath(final JsonIterator iter, int value) throws IOException {
516+
value = -value; // add negatives to avoid redundant checks for Integer.MIN_VALUE on each iteration
517+
int multmin = -214748364; // limit / 10
514518
for (; ; ) {
515519
for (int i = iter.head; i < iter.tail; i++) {
516520
int ind = IterImplNumber.intDigits[iter.buf[i]];
517521
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
518522
iter.head = i;
519523
return value;
520524
}
521-
if (value == Integer.MIN_VALUE) {
525+
if (value < multmin) {
522526
throw iter.reportError("readIntSlowPath", "value is too large for int");
523527
}
524-
value = (value << 3) + (value << 1) + ind;
525-
if (value < 0 && value != Integer.MIN_VALUE) {
528+
value = (value << 3) + (value << 1) - ind;
529+
if (value >= 0) {
526530
throw iter.reportError("readIntSlowPath", "value is too large for int");
527531
}
528532
}
@@ -582,32 +586,30 @@ public static final String readNumber(final JsonIterator iter) throws IOExceptio
582586
}
583587
}
584588

585-
586-
static final double readPositiveDouble(final JsonIterator iter) throws IOException {
589+
static final double readDouble(final JsonIterator iter) throws IOException {
587590
return readDoubleSlowPath(iter);
588591
}
589592

590-
591-
static final long readPositiveLong(final JsonIterator iter, byte c) throws IOException {
593+
static final long readLong(final JsonIterator iter, final byte c) throws IOException {
592594
long ind = IterImplNumber.intDigits[c];
593595
if (ind == 0) {
594596
assertNotLeadingZero(iter);
595597
return 0;
596598
}
597599
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
598-
throw iter.reportError("readPositiveLong", "expect 0~9");
600+
throw iter.reportError("readLong", "expect 0~9");
599601
}
600602
return IterImplForStreaming.readLongSlowPath(iter, ind);
601603
}
602604

603-
static final int readPositiveInt(final JsonIterator iter, byte c) throws IOException {
605+
static final int readInt(final JsonIterator iter, final byte c) throws IOException {
604606
int ind = IterImplNumber.intDigits[c];
605607
if (ind == 0) {
606608
assertNotLeadingZero(iter);
607609
return 0;
608610
}
609611
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
610-
throw iter.reportError("readPositiveInt", "expect 0~9");
612+
throw iter.reportError("readInt", "expect 0~9");
611613
}
612614
return IterImplForStreaming.readIntSlowPath(iter, ind);
613615
}
@@ -620,7 +622,7 @@ static void assertNotLeadingZero(JsonIterator iter) throws IOException {
620622
if (ind2 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
621623
return;
622624
}
623-
throw iter.reportError("readPositiveInt", "leading zero is invalid");
625+
throw iter.reportError("assertNotLeadingZero", "leading zero is invalid");
624626
} catch (ArrayIndexOutOfBoundsException e) {
625627
iter.head = iter.tail;
626628
return;

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

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3131
*/
3232
package com.jsoniter;
3333

34-
import com.jsoniter.spi.JsonException;
35-
3634
import java.io.IOException;
3735

3836
class IterImplNumber {
@@ -66,39 +64,40 @@ class IterImplNumber {
6664
public static final double readDouble(final JsonIterator iter) throws IOException {
6765
final byte c = IterImpl.nextToken(iter);
6866
if (c == '-') {
69-
return -IterImpl.readPositiveDouble(iter);
67+
return -IterImpl.readDouble(iter);
7068
} else {
7169
iter.unreadByte();
72-
return IterImpl.readPositiveDouble(iter);
70+
return IterImpl.readDouble(iter);
7371
}
7472
}
7573

7674
public static final float readFloat(final JsonIterator iter) throws IOException {
77-
final byte c = IterImpl.nextToken(iter);
78-
if (c == '-') {
79-
return (float)-IterImpl.readPositiveDouble(iter);
80-
} else {
81-
iter.unreadByte();
82-
return (float) IterImpl.readPositiveDouble(iter);
83-
}
75+
return (float) IterImplNumber.readDouble(iter);
8476
}
8577

8678
public static final int readInt(final JsonIterator iter) throws IOException {
8779
byte c = IterImpl.nextToken(iter);
8880
if (c == '-') {
89-
return -IterImpl.readPositiveInt(iter, IterImpl.readByte(iter));
81+
return IterImpl.readInt(iter, IterImpl.readByte(iter));
9082
} else {
91-
return IterImpl.readPositiveInt(iter, c);
83+
int val = IterImpl.readInt(iter, c);
84+
if (val == Integer.MIN_VALUE) {
85+
throw iter.reportError("readInt", "value is too large for int");
86+
}
87+
return -val;
9288
}
9389
}
9490

9591
public static final long readLong(JsonIterator iter) throws IOException {
9692
byte c = IterImpl.nextToken(iter);
9793
if (c == '-') {
98-
return -IterImpl.readPositiveLong(iter, IterImpl.readByte(iter));
94+
return IterImpl.readLong(iter, IterImpl.readByte(iter));
9995
} else {
100-
return IterImpl.readPositiveLong(iter, c);
96+
long val = IterImpl.readLong(iter, c);
97+
if (val == Long.MIN_VALUE) {
98+
throw iter.reportError("readLong", "value is too large for long");
99+
}
100+
return -val;
101101
}
102102
}
103-
104103
}

src/test/java/com/jsoniter/TestFloat.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,15 @@ public void test_ieee_754() throws IOException {
3434
public void test_decimal_places() throws IOException {
3535
assertEquals(Long.MAX_VALUE, parseFloat("9223372036854775807,"), 0.01f);
3636
assertEquals(Long.MAX_VALUE, parseDouble("9223372036854775807,"), 0.01f);
37+
assertEquals(Long.MIN_VALUE, parseDouble("-9223372036854775808,"), 0.01f);
3738
assertEquals(9923372036854775807f, parseFloat("9923372036854775807,"), 0.01f);
39+
assertEquals(-9923372036854775808f, parseFloat("-9923372036854775808,"), 0.01f);
3840
assertEquals(9923372036854775807d, parseDouble("9923372036854775807,"), 0.01f);
41+
assertEquals(-9923372036854775808d, parseDouble("-9923372036854775808,"), 0.01f);
3942
assertEquals(720368.54775807f, parseFloat("720368.54775807,"), 0.01f);
43+
assertEquals(-720368.54775807f, parseFloat("-720368.54775807,"), 0.01f);
4044
assertEquals(720368.54775807d, parseDouble("720368.54775807,"), 0.01f);
45+
assertEquals(-720368.54775807d, parseDouble("-720368.54775807,"), 0.01f);
4146
assertEquals(72036.854775807f, parseFloat("72036.854775807,"), 0.01f);
4247
assertEquals(72036.854775807d, parseDouble("72036.854775807,"), 0.01f);
4348
assertEquals(720368.54775807f, parseFloat("720368.547758075,"), 0.01f);

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

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,39 @@ public void test_max_min_long() throws IOException {
6464

6565
public void test_large_number() throws IOException {
6666
try {
67-
JsonIterator.deserialize(Integer.toString(Integer.MIN_VALUE) + "1", Integer.class);
67+
JsonIterator.deserialize("2147483648", Integer.class);
6868
fail();
6969
} catch (JsonException e) {
7070
}
71+
for (int i = 300000000; i < 2000000000; i += 10000000) {
72+
try {
73+
JsonIterator.deserialize(i + "0", Integer.class);
74+
fail();
75+
} catch (JsonException e) {
76+
}
77+
try {
78+
JsonIterator.deserialize(-i + "0", Integer.class);
79+
fail();
80+
} catch (JsonException e) {
81+
}
82+
}
7183
try {
72-
JsonIterator.deserialize(Long.toString(Long.MAX_VALUE) + "1", Long.class);
84+
JsonIterator.deserialize("9223372036854775808", Long.class);
7385
fail();
7486
} catch (JsonException e) {
7587
}
88+
for (long i = 1000000000000000000L; i < 9000000000000000000L; i += 100000000000000000L) {
89+
try {
90+
JsonIterator.deserialize(i + "0", Long.class);
91+
fail();
92+
} catch (JsonException e) {
93+
}
94+
try {
95+
JsonIterator.deserialize(-i + "0", Long.class);
96+
fail();
97+
} catch (JsonException e) {
98+
}
99+
}
76100
}
77101

78102
public void test_byte() throws IOException {

0 commit comments

Comments
 (0)