Skip to content

Commit c23e009

Browse files
committed
optimize encode string and decode integer
1 parent f2114f7 commit c23e009

2 files changed

Lines changed: 89 additions & 26 deletions

File tree

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

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3636
// TODO: make separate implementation for streaming and non-streaming
3737
class IterImplNumber {
3838

39-
private final static int[] intDigits = new int[256];
40-
private final static int[] floatDigits = new int[256];
39+
private final static int[] intDigits = new int[127];
40+
private final static int[] floatDigits = new int[127];
4141
private final static int END_OF_NUMBER = -2;
4242
private final static int DOT_IN_NUMBER = -3;
4343
private final static int INVALID_CHAR_FOR_NUMBER = -1;
@@ -88,11 +88,12 @@ private static final double readPositiveDouble(final JsonIterator iter) throws I
8888
return value;
8989
case DOT_IN_NUMBER:
9090
break non_decimal_loop;
91-
}
92-
value = (value << 3) + (value << 1) + ind; // value = value * 10 + ind;
93-
if (value < 0) {
94-
// overflow
95-
return readDoubleSlowPath(iter);
91+
default:
92+
value = (value << 3) + (value << 1) + ind; // value = value * 10 + ind;
93+
if (value < 0) {
94+
// overflow
95+
return readDoubleSlowPath(iter);
96+
}
9697
}
9798
}
9899
if (c == '.') {
@@ -112,12 +113,13 @@ private static final double readPositiveDouble(final JsonIterator iter) throws I
112113
case INVALID_CHAR_FOR_NUMBER:
113114
case DOT_IN_NUMBER:
114115
return readDoubleSlowPath(iter);
115-
}
116-
decimalPlaces++;
117-
value = (value << 3) + (value << 1) + ind; // value = value * 10 + ind;
118-
if (value < 0) {
119-
// overflow
120-
return readDoubleSlowPath(iter);
116+
default:
117+
decimalPlaces++;
118+
value = (value << 3) + (value << 1) + ind; // value = value * 10 + ind;
119+
if (value < 0) {
120+
// overflow
121+
return readDoubleSlowPath(iter);
122+
}
121123
}
122124
}
123125
}
@@ -257,10 +259,58 @@ public static final int readPositiveInt(final JsonIterator iter, byte c) throws
257259
if (ind == INVALID_CHAR_FOR_NUMBER) {
258260
throw iter.reportError("readPositiveInt", "expect 0~9");
259261
}
260-
int value = ind;
262+
if (iter.tail - iter.head < 8) {
263+
return readIntSlowPath(iter, ind);
264+
}
265+
int i = iter.head;
266+
int ind2 = intDigits[iter.buf[i]];
267+
if (ind2 == INVALID_CHAR_FOR_NUMBER) {
268+
iter.head = i;
269+
return ind;
270+
}
271+
int ind3 = intDigits[iter.buf[++i]];
272+
if (ind3 == INVALID_CHAR_FOR_NUMBER) {
273+
iter.head = i;
274+
return ind * 10 + ind2;
275+
}
276+
int ind4 = intDigits[iter.buf[++i]];
277+
if (ind4 == INVALID_CHAR_FOR_NUMBER) {
278+
iter.head = i;
279+
return ind * 100 + ind2 * 10 + ind3;
280+
}
281+
int ind5 = intDigits[iter.buf[++i]];
282+
if (ind5 == INVALID_CHAR_FOR_NUMBER) {
283+
iter.head = i;
284+
return ind * 1000 + ind2 * 100 + ind3 * 10 + ind4;
285+
}
286+
int ind6 = intDigits[iter.buf[++i]];
287+
if (ind6 == INVALID_CHAR_FOR_NUMBER) {
288+
iter.head = i;
289+
return ind * 10000 + ind2 * 1000 + ind3 * 100 + ind4 * 10 + ind5;
290+
}
291+
int ind7 = intDigits[iter.buf[++i]];
292+
if (ind7 == INVALID_CHAR_FOR_NUMBER) {
293+
iter.head = i;
294+
return ind * 100000 + ind2 * 10000 + ind3 * 1000 + ind4 * 100 + ind5 * 10 + ind6;
295+
}
296+
int ind8 = intDigits[iter.buf[++i]];
297+
if (ind8 == INVALID_CHAR_FOR_NUMBER) {
298+
iter.head = i;
299+
return ind * 1000000 + ind2 * 100000 + ind3 * 10000 + ind4 * 1000 + ind5 * 100 + ind6 * 10 + ind7;
300+
}
301+
int ind9 = intDigits[iter.buf[++i]];
302+
int val = ind * 10000000 + ind2 * 1000000 + ind3 * 100000 + ind4 * 10000 + ind5 * 1000 + ind6 * 100 + ind7 * 10 + ind8;
303+
iter.head = i;
304+
if (ind9 == INVALID_CHAR_FOR_NUMBER) {
305+
return val;
306+
}
307+
return readIntSlowPath(iter, val);
308+
}
309+
310+
private static int readIntSlowPath(JsonIterator iter, int value) throws IOException {
261311
for (; ; ) {
262312
for (int i = iter.head; i < iter.tail; i++) {
263-
ind = intDigits[iter.buf[i]];
313+
int ind = intDigits[iter.buf[i]];
264314
if (ind == INVALID_CHAR_FOR_NUMBER) {
265315
iter.head = i;
266316
return value;

src/main/java/com/jsoniter/output/StreamImplString.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ class StreamImplString {
3838
private static final byte[] ITOA = new byte[]{
3939
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
4040
'a', 'b', 'c', 'd', 'e', 'f'};
41+
private static final boolean[] CAN_DIRECT_WRITE = new boolean[128];
42+
43+
static {
44+
for (int i = 0; i < CAN_DIRECT_WRITE.length; i++) {
45+
if (i > 31 && i < 126 && i != '"' && i != '\\') {
46+
CAN_DIRECT_WRITE[i] = true;
47+
}
48+
}
49+
}
4150

4251
public static final void writeString(final JsonStream stream, final String val) throws IOException {
4352
int i = 0;
@@ -58,9 +67,13 @@ public static final void writeString(final JsonStream stream, final String val)
5867
// write string, the fast path, without utf8 and escape support
5968
for (; i < toWriteLen; i++) {
6069
char c = val.charAt(i);
61-
if (c > 31 && c != '"' && c != '\\' && c < 126) {
62-
stream.buf[n++] = (byte) c;
63-
} else {
70+
try {
71+
if (CAN_DIRECT_WRITE[c]) {
72+
stream.buf[n++] = (byte) c;
73+
} else {
74+
break;
75+
}
76+
} catch (ArrayIndexOutOfBoundsException e) {
6477
break;
6578
}
6679
}
@@ -116,29 +129,29 @@ private static void writeStringSlowPath(JsonStream stream, String val, int i, in
116129
byte b3 = (byte) (c >> 4 & 0xf);
117130
byte b2 = (byte) (c >> 8 & 0xf);
118131
byte b1 = (byte) (c >> 12 & 0xf);
119-
stream.write((byte)'\\', (byte)'u', ITOA[b1], ITOA[b2], ITOA[b3], ITOA[b4]);
132+
stream.write((byte) '\\', (byte) 'u', ITOA[b1], ITOA[b2], ITOA[b3], ITOA[b4]);
120133
} else {
121134
switch (c) {
122135
case '"':
123-
stream.write((byte)'\\', (byte)'"');
136+
stream.write((byte) '\\', (byte) '"');
124137
break;
125138
case '\\':
126-
stream.write((byte)'\\', (byte)'\\');
139+
stream.write((byte) '\\', (byte) '\\');
127140
break;
128141
case '\b':
129-
stream.write((byte)'\\', (byte)'b');
142+
stream.write((byte) '\\', (byte) 'b');
130143
break;
131144
case '\f':
132-
stream.write((byte)'\\', (byte)'f');
145+
stream.write((byte) '\\', (byte) 'f');
133146
break;
134147
case '\n':
135-
stream.write((byte)'\\', (byte)'n');
148+
stream.write((byte) '\\', (byte) 'n');
136149
break;
137150
case '\r':
138-
stream.write((byte)'\\', (byte)'r');
151+
stream.write((byte) '\\', (byte) 'r');
139152
break;
140153
case '\t':
141-
stream.write((byte)'\\', (byte)'t');
154+
stream.write((byte) '\\', (byte) 't');
142155
break;
143156
default:
144157
stream.write(c);

0 commit comments

Comments
 (0)