Skip to content

Commit 5161682

Browse files
committed
optimize read double
1 parent c23e009 commit 5161682

File tree

5 files changed

+285
-292
lines changed

5 files changed

+285
-292
lines changed

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

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.jsoniter;
22

33
import com.jsoniter.any.Any;
4+
import com.jsoniter.spi.JsonException;
45

56
import java.io.IOException;
67

@@ -302,4 +303,142 @@ public final static int readStringSlowPath(JsonIterator iter, int j) throws IOEx
302303
public static int updateStringCopyBound(final JsonIterator iter, final int bound) {
303304
return bound;
304305
}
306+
307+
static final int readPositiveInt(final JsonIterator iter, byte c) throws IOException {
308+
int ind = IterImplNumber.intDigits[c];
309+
if (ind == 0) {
310+
return 0;
311+
}
312+
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
313+
throw iter.reportError("readPositiveInt", "expect 0~9");
314+
}
315+
int i = iter.head;
316+
int ind2 = IterImplNumber.intDigits[iter.buf[i]];
317+
if (ind2 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
318+
iter.head = i;
319+
return ind;
320+
}
321+
int ind3 = IterImplNumber.intDigits[iter.buf[++i]];
322+
if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
323+
iter.head = i;
324+
return ind * 10 + ind2;
325+
}
326+
int ind4 = IterImplNumber.intDigits[iter.buf[++i]];
327+
if (ind4 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
328+
iter.head = i;
329+
return ind * 100 + ind2 * 10 + ind3;
330+
}
331+
int ind5 = IterImplNumber.intDigits[iter.buf[++i]];
332+
if (ind5 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
333+
iter.head = i;
334+
return ind * 1000 + ind2 * 100 + ind3 * 10 + ind4;
335+
}
336+
int ind6 = IterImplNumber.intDigits[iter.buf[++i]];
337+
if (ind6 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
338+
iter.head = i;
339+
return ind * 10000 + ind2 * 1000 + ind3 * 100 + ind4 * 10 + ind5;
340+
}
341+
int ind7 = IterImplNumber.intDigits[iter.buf[++i]];
342+
if (ind7 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
343+
iter.head = i;
344+
return ind * 100000 + ind2 * 10000 + ind3 * 1000 + ind4 * 100 + ind5 * 10 + ind6;
345+
}
346+
int ind8 = IterImplNumber.intDigits[iter.buf[++i]];
347+
if (ind8 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
348+
iter.head = i;
349+
return ind * 1000000 + ind2 * 100000 + ind3 * 10000 + ind4 * 1000 + ind5 * 100 + ind6 * 10 + ind7;
350+
}
351+
int ind9 = IterImplNumber.intDigits[iter.buf[++i]];
352+
int val = ind * 10000000 + ind2 * 1000000 + ind3 * 100000 + ind4 * 10000 + ind5 * 1000 + ind6 * 100 + ind7 * 10 + ind8;
353+
iter.head = i;
354+
if (ind9 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
355+
return val;
356+
}
357+
return IterImplForStreaming.readIntSlowPath(iter, val);
358+
}
359+
360+
static final long readPositiveLong(final JsonIterator iter, byte c) throws IOException {
361+
long ind = IterImplNumber.intDigits[c];
362+
if (ind == 0) {
363+
return 0;
364+
}
365+
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
366+
throw iter.reportError("readPositiveLong", "expect 0~9");
367+
}
368+
int i = iter.head;
369+
int ind2 = IterImplNumber.intDigits[iter.buf[i]];
370+
if (ind2 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
371+
iter.head = i;
372+
return ind;
373+
}
374+
int ind3 = IterImplNumber.intDigits[iter.buf[++i]];
375+
if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
376+
iter.head = i;
377+
return ind * 10 + ind2;
378+
}
379+
int ind4 = IterImplNumber.intDigits[iter.buf[++i]];
380+
if (ind4 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
381+
iter.head = i;
382+
return ind * 100 + ind2 * 10 + ind3;
383+
}
384+
int ind5 = IterImplNumber.intDigits[iter.buf[++i]];
385+
if (ind5 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
386+
iter.head = i;
387+
return ind * 1000 + ind2 * 100 + ind3 * 10 + ind4;
388+
}
389+
int ind6 = IterImplNumber.intDigits[iter.buf[++i]];
390+
if (ind6 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
391+
iter.head = i;
392+
return ind * 10000 + ind2 * 1000 + ind3 * 100 + ind4 * 10 + ind5;
393+
}
394+
int ind7 = IterImplNumber.intDigits[iter.buf[++i]];
395+
if (ind7 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
396+
iter.head = i;
397+
return ind * 100000 + ind2 * 10000 + ind3 * 1000 + ind4 * 100 + ind5 * 10 + ind6;
398+
}
399+
int ind8 = IterImplNumber.intDigits[iter.buf[++i]];
400+
if (ind8 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
401+
iter.head = i;
402+
return ind * 1000000 + ind2 * 100000 + ind3 * 10000 + ind4 * 1000 + ind5 * 100 + ind6 * 10 + ind7;
403+
}
404+
int ind9 = IterImplNumber.intDigits[iter.buf[++i]];
405+
long val = ind * 10000000 + ind2 * 1000000 + ind3 * 100000 + ind4 * 10000 + ind5 * 1000 + ind6 * 100 + ind7 * 10 + ind8;
406+
iter.head = i;
407+
if (ind9 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
408+
return val;
409+
}
410+
return IterImplForStreaming.readLongSlowPath(iter, val);
411+
}
412+
413+
static final double readPositiveDouble(final JsonIterator iter) throws IOException {
414+
int oldHead = iter.head;
415+
try {
416+
long value = IterImplNumber.readLong(iter); // without the dot
417+
byte c = iter.buf[iter.head];
418+
if (c == '.') {
419+
iter.head++;
420+
int start = iter.head;
421+
c = iter.buf[iter.head++];
422+
long decimalPart = readPositiveLong(iter, c);
423+
int decimalPlaces = iter.head - start;
424+
if (decimalPlaces > 0 && decimalPlaces < IterImplNumber.POW10.length && (iter.head - oldHead) < 10) {
425+
value = value * IterImplNumber.POW10[decimalPlaces] + decimalPart;
426+
return value / (double) IterImplNumber.POW10[decimalPlaces];
427+
} else {
428+
iter.head = oldHead;
429+
return IterImplForStreaming.readDoubleSlowPath(iter);
430+
}
431+
} else {
432+
if (iter.head < iter.tail && iter.buf[iter.head] == 'e') {
433+
iter.head = oldHead;
434+
return IterImplForStreaming.readDoubleSlowPath(iter);
435+
} else {
436+
return value;
437+
}
438+
}
439+
} catch (JsonException e) {
440+
iter.head = oldHead;
441+
return IterImplForStreaming.readDoubleSlowPath(iter);
442+
}
443+
}
305444
}

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

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,4 +467,129 @@ public final static int readStringSlowPath(JsonIterator iter, int j) throws IOEx
467467
}
468468
}
469469

470+
static long readLongSlowPath(JsonIterator iter, long value) throws IOException {
471+
for (; ; ) {
472+
for (int i = iter.head; i < iter.tail; i++) {
473+
int ind = IterImplNumber.intDigits[iter.buf[i]];
474+
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
475+
iter.head = i;
476+
return value;
477+
}
478+
value = (value << 3) + (value << 1) + ind;
479+
if (value < 0) {
480+
// overflow
481+
if (value == Long.MIN_VALUE) {
482+
// if there is more number following, subsequent read will fail anyway
483+
iter.head = i;
484+
return value;
485+
} else {
486+
throw iter.reportError("readPositiveLong", "value is too large for long");
487+
}
488+
}
489+
}
490+
if (!IterImpl.loadMore(iter)) {
491+
return value;
492+
}
493+
}
494+
}
495+
496+
static int readIntSlowPath(JsonIterator iter, int value) throws IOException {
497+
for (; ; ) {
498+
for (int i = iter.head; i < iter.tail; i++) {
499+
int ind = IterImplNumber.intDigits[iter.buf[i]];
500+
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
501+
iter.head = i;
502+
return value;
503+
}
504+
value = (value << 3) + (value << 1) + ind;
505+
if (value < 0) {
506+
// overflow
507+
if (value == Integer.MIN_VALUE) {
508+
// if there is more number following, subsequent read will fail anyway
509+
iter.head = i;
510+
return value;
511+
} else {
512+
throw iter.reportError("readPositiveInt", "value is too large for int");
513+
}
514+
}
515+
}
516+
if (!IterImpl.loadMore(iter)) {
517+
return value;
518+
}
519+
}
520+
}
521+
522+
public static final double readDoubleSlowPath(final JsonIterator iter) throws IOException {
523+
try {
524+
return Double.valueOf(readNumber(iter));
525+
} catch (NumberFormatException e) {
526+
throw iter.reportError("readDoubleSlowPath", e.toString());
527+
}
528+
}
529+
530+
public static final String readNumber(final JsonIterator iter) throws IOException {
531+
int j = 0;
532+
for (; ; ) {
533+
for (int i = iter.head; i < iter.tail; i++) {
534+
if (j == iter.reusableChars.length) {
535+
char[] newBuf = new char[iter.reusableChars.length * 2];
536+
System.arraycopy(iter.reusableChars, 0, newBuf, 0, iter.reusableChars.length);
537+
iter.reusableChars = newBuf;
538+
}
539+
byte c = iter.buf[i];
540+
switch (c) {
541+
case '-':
542+
case '.':
543+
case 'e':
544+
case 'E':
545+
case '0':
546+
case '1':
547+
case '2':
548+
case '3':
549+
case '4':
550+
case '5':
551+
case '6':
552+
case '7':
553+
case '8':
554+
case '9':
555+
iter.reusableChars[j++] = (char) c;
556+
break;
557+
default:
558+
iter.head = i;
559+
return new String(iter.reusableChars, 0, j);
560+
}
561+
}
562+
if (!IterImpl.loadMore(iter)) {
563+
return new String(iter.reusableChars, 0, j);
564+
}
565+
}
566+
}
567+
568+
569+
static final double readPositiveDouble(final JsonIterator iter) throws IOException {
570+
return readDoubleSlowPath(iter);
571+
}
572+
573+
574+
static final long readPositiveLong(final JsonIterator iter, byte c) throws IOException {
575+
long ind = IterImplNumber.intDigits[c];
576+
if (ind == 0) {
577+
return 0;
578+
}
579+
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
580+
throw iter.reportError("readPositiveLong", "expect 0~9");
581+
}
582+
return IterImplForStreaming.readLongSlowPath(iter, ind);
583+
}
584+
585+
static final int readPositiveInt(final JsonIterator iter, byte c) throws IOException {
586+
int ind = IterImplNumber.intDigits[c];
587+
if (ind == 0) {
588+
return 0;
589+
}
590+
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
591+
throw iter.reportError("readPositiveInt", "expect 0~9");
592+
}
593+
return IterImplForStreaming.readIntSlowPath(iter, ind);
594+
}
470595
}

0 commit comments

Comments
 (0)