FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

optimize read int32 · lyBigdata/java@e8a5956 · GitHub

/ java Public
forked from json-iterator/java

Commit e8a5956

Browse files
committed
optimize read int32
1 parent 648fee0 commit e8a5956

3 files changed

Lines changed: 90 additions & 40 deletions

File tree

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

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,36 +33,41 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3333

3434
import java.io.IOException;
3535

36+
// TODO: make separate implementation for streaming and non-streaming
3637
class IterImplNumber {
3738

3839
final static int[] digits = new int[256];
39-
final static int[] zeroToNineDigits = new int[256];
40-
final static int END_OF_NUMBER = -2;
41-
final static int DOT_IN_NUMBER = -3;
42-
final static int INVALID_CHAR_FOR_NUMBER = -1;
40+
private final static int[] intDigits = new int[256];
41+
private final static int[] floatDigits = new int[256];
42+
private final static int END_OF_NUMBER = -2;
43+
private final static int DOT_IN_NUMBER = -3;
44+
private final static int INVALID_CHAR_FOR_NUMBER = -1;
4345
private static final int POW10[] = {1, 10, 100, 1000, 10000, 100000, 1000000};
44-
private final static long SAFE_TO_MULTIPLY_10 = (Long.MAX_VALUE / 10) - 10;
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;
4548

4649
static {
4750
for (int i = 0; i < digits.length; i++) {
4851
digits[i] = INVALID_CHAR_FOR_NUMBER;
49-
zeroToNineDigits[i] = INVALID_CHAR_FOR_NUMBER;
52+
floatDigits[i] = INVALID_CHAR_FOR_NUMBER;
53+
intDigits[i] = INVALID_CHAR_FOR_NUMBER;
5054
}
5155
for (int i = '0'; i <= '9'; ++i) {
5256
digits[i] = (i - '0');
53-
zeroToNineDigits[i] = (i - '0');
57+
floatDigits[i] = (i - '0');
58+
intDigits[i] = (i - '0');
5459
}
5560
for (int i = 'a'; i <= 'f'; ++i) {
5661
digits[i] = ((i - 'a') + 10);
5762
}
5863
for (int i = 'A'; i <= 'F'; ++i) {
5964
digits[i] = ((i - 'A') + 10);
6065
}
61-
zeroToNineDigits[','] = END_OF_NUMBER;
62-
zeroToNineDigits[']'] = END_OF_NUMBER;
63-
zeroToNineDigits['}'] = END_OF_NUMBER;
64-
zeroToNineDigits[' '] = END_OF_NUMBER;
65-
zeroToNineDigits['.'] = DOT_IN_NUMBER;
66+
floatDigits[','] = END_OF_NUMBER;
67+
floatDigits[']'] = END_OF_NUMBER;
68+
floatDigits['}'] = END_OF_NUMBER;
69+
floatDigits[' '] = END_OF_NUMBER;
70+
floatDigits['.'] = DOT_IN_NUMBER;
6671
}
6772

6873
public static final double readDouble(final JsonIterator iter) throws IOException {
@@ -82,7 +87,7 @@ private static final double readPositiveDouble(final JsonIterator iter) throws I
8287
non_decimal_loop:
8388
for (; i < iter.tail; i++) {
8489
c = iter.buf[i];
85-
final int ind = zeroToNineDigits[c];
90+
final int ind = floatDigits[c];
8691
switch (ind) {
8792
case INVALID_CHAR_FOR_NUMBER:
8893
return readDoubleSlowPath(iter);
@@ -92,7 +97,7 @@ private static final double readPositiveDouble(final JsonIterator iter) throws I
9297
case DOT_IN_NUMBER:
9398
break non_decimal_loop;
9499
}
95-
if (value > SAFE_TO_MULTIPLY_10) {
100+
if (value > LONG_SAFE_TO_MULTIPLY_10) {
96101
return readDoubleSlowPath(iter);
97102
}
98103
value = (value << 3) + (value << 1) + ind; // value = value * 10 + ind;
@@ -102,7 +107,7 @@ private static final double readPositiveDouble(final JsonIterator iter) throws I
102107
int decimalPlaces = 0;
103108
for (; i < iter.tail; i++) {
104109
c = iter.buf[i];
105-
final int ind = zeroToNineDigits[c];
110+
final int ind = floatDigits[c];
106111
switch (ind) {
107112
case END_OF_NUMBER:
108113
if (decimalPlaces > 0 && decimalPlaces < POW10.length) {
@@ -116,7 +121,7 @@ private static final double readPositiveDouble(final JsonIterator iter) throws I
116121
return readDoubleSlowPath(iter);
117122
}
118123
decimalPlaces++;
119-
if (value > SAFE_TO_MULTIPLY_10) {
124+
if (value > LONG_SAFE_TO_MULTIPLY_10) {
120125
return readDoubleSlowPath(iter);
121126
}
122127
value = (value << 3) + (value << 1) + ind; // value = value * 10 + ind;
@@ -150,7 +155,7 @@ private static final float readPositiveFloat(final JsonIterator iter) throws IOE
150155
non_decimal_loop:
151156
for (; i < iter.tail; i++) {
152157
c = iter.buf[i];
153-
final int ind = zeroToNineDigits[c];
158+
final int ind = floatDigits[c];
154159
switch (ind) {
155160
case INVALID_CHAR_FOR_NUMBER:
156161
return readFloatSlowPath(iter);
@@ -160,7 +165,7 @@ private static final float readPositiveFloat(final JsonIterator iter) throws IOE
160165
case DOT_IN_NUMBER:
161166
break non_decimal_loop;
162167
}
163-
if (value > SAFE_TO_MULTIPLY_10) {
168+
if (value > LONG_SAFE_TO_MULTIPLY_10) {
164169
return readFloatSlowPath(iter);
165170
}
166171
value = (value << 3) + (value << 1) + ind; // value = value * 10 + ind;
@@ -170,7 +175,7 @@ private static final float readPositiveFloat(final JsonIterator iter) throws IOE
170175
int decimalPlaces = 0;
171176
for (; i < iter.tail; i++) {
172177
c = iter.buf[i];
173-
final int ind = zeroToNineDigits[c];
178+
final int ind = floatDigits[c];
174179
switch (ind) {
175180
case END_OF_NUMBER:
176181
if (decimalPlaces > 0 && decimalPlaces < POW10.length) {
@@ -184,7 +189,7 @@ private static final float readPositiveFloat(final JsonIterator iter) throws IOE
184189
return readFloatSlowPath(iter);
185190
}
186191
decimalPlaces++;
187-
if (value > SAFE_TO_MULTIPLY_10) {
192+
if (value > LONG_SAFE_TO_MULTIPLY_10) {
188193
return readFloatSlowPath(iter);
189194
}
190195
value = (value << 3) + (value << 1) + ind; // value = value * 10 + ind;
@@ -239,37 +244,39 @@ public static final String readNumber(final JsonIterator iter) throws IOExceptio
239244
}
240245
}
241246

242-
public static final int readInt(JsonIterator iter) throws IOException {
247+
public static final int readInt(final JsonIterator iter) throws IOException {
243248
byte c = IterImpl.nextToken(iter);
244249
if (c == '-') {
245-
return -readUnsignedInt(iter);
250+
return -readUnsignedInt(iter, IterImpl.readByte(iter));
246251
} else {
247-
iter.unreadByte();
248-
return readUnsignedInt(iter);
252+
return readUnsignedInt(iter, c);
249253
}
250254
}
251255

252-
public static final int readUnsignedInt(JsonIterator iter) throws IOException {
253-
// TODO: throw overflow
254-
byte c = IterImpl.readByte(iter);
255-
int v = digits[c];
256-
if (v == 0) {
256+
public static final int readUnsignedInt(final JsonIterator iter, byte c) throws IOException {
257+
int result = intDigits[c];
258+
if (result == 0) {
257259
return 0;
258260
}
259-
if (v == -1) {
261+
if (result == INVALID_CHAR_FOR_NUMBER) {
260262
throw iter.reportError("readUnsignedInt", "expect 0~9");
261263
}
262-
int result = 0;
263-
for (; ; ) {
264-
result = result * 10 + v;
265-
c = IterImpl.readByte(iter);
266-
v = digits[c];
267-
if (v == -1) {
268-
iter.unreadByte();
269-
break;
264+
for (;;) {
265+
for (int i = iter.head; i < iter.tail; i++) {
266+
int ind = intDigits[iter.buf[i]];
267+
if (ind == INVALID_CHAR_FOR_NUMBER) {
268+
iter.head = i;
269+
return result;
270+
}
271+
if (result > INT_SAFE_TO_MULTIPLY_10) {
272+
throw iter.reportError("readUnsignedInt", "value is too large for int");
273+
}
274+
result = (result << 3) + (result << 1) + ind;
275+
}
276+
if (!IterImpl.loadMore(iter)) {
277+
return result;
270278
}
271279
}
272-
return result;
273280
}
274281

275282
public static final long readLong(JsonIterator iter) throws IOException {

‎src/main/java/com/jsoniter/JsonIterator.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public final short readShort() throws IOException {
168168
if (Short.MIN_VALUE <= v && v <= Short.MAX_VALUE) {
169169
return (short) v;
170170
} else {
171-
throw new JsonException("short overflow: " + v);
171+
throw reportError("readShort", "short overflow: " + v);
172172
}
173173
}
174174

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.jsoniter;
2+
3+
import com.jsoniter.spi.JsonException;
4+
import junit.framework.TestCase;
5+
import org.junit.experimental.categories.Category;
6+
7+
import java.io.ByteArrayInputStream;
8+
import java.io.IOException;
9+
10+
public class TestInteger extends TestCase {
11+
12+
private boolean isStreaming;
13+
14+
public void test_positive_negative() throws IOException {
15+
assertEquals(4321, parseInt("4321"));
16+
assertEquals(-4321, parseInt("-4321"));
17+
}
18+
19+
public void test_large_number() throws IOException {
20+
try {
21+
parseInt("123456789123456789");
22+
fail();
23+
} catch (JsonException e) {
24+
}
25+
}
26+
27+
@Category(StreamingCategory.class)
28+
public void test_streaming() throws IOException {
29+
isStreaming = true;
30+
test_positive_negative();
31+
test_large_number();
32+
}
33+
34+
private int parseInt(String input) throws IOException {
35+
if (isStreaming) {
36+
JsonIterator iter = JsonIterator.parse(new ByteArrayInputStream(input.getBytes()), 2);
37+
return iter.readInt();
38+
} else {
39+
JsonIterator iter = JsonIterator.parse(input);
40+
return iter.readInt();
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL