Skip to content

Commit 0890724

Browse files
committed
make read any work with streaming
1 parent f45bef6 commit 0890724

File tree

5 files changed

+149
-44
lines changed

5 files changed

+149
-44
lines changed

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

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

3+
import com.jsoniter.any.Any;
4+
35
import java.io.IOException;
46

57
class IterImpl {
@@ -159,4 +161,44 @@ final static byte readByte(JsonIterator iter) throws IOException {
159161
}
160162
return iter.buf[iter.head++];
161163
}
164+
165+
public static Any readAny(JsonIterator iter) throws IOException {
166+
int start = iter.head;
167+
byte c = nextToken(iter);
168+
switch (c) {
169+
case '"':
170+
skipString(iter);
171+
return Any.lazyString(iter.buf, start, iter.head);
172+
case '-':
173+
case '0':
174+
case '1':
175+
case '2':
176+
case '3':
177+
case '4':
178+
case '5':
179+
case '6':
180+
case '7':
181+
case '8':
182+
case '9':
183+
skipUntilBreak(iter);
184+
return Any.lazyNumber(iter.buf, start, iter.head);
185+
case 't':
186+
skipUntilBreak(iter);
187+
return Any.wrap(true);
188+
case 'f':
189+
skipUntilBreak(iter);
190+
return Any.wrap(false);
191+
case 'n':
192+
skipUntilBreak(iter);
193+
return Any.wrap((Object)null);
194+
case '[':
195+
skipArray(iter);
196+
return Any.lazyArray(iter.buf, start, iter.head);
197+
case '{':
198+
skipObject(iter);
199+
return Any.lazyObject(iter.buf, start, iter.head);
200+
default:
201+
throw iter.reportError("IterImplSkip", "do not know how to skip: " + c);
202+
}
203+
}
162204
}

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

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

3+
import com.jsoniter.any.Any;
4+
35
import java.io.IOException;
46

57
class IterImplForStreaming {
@@ -227,6 +229,9 @@ final static boolean loadMore(JsonIterator iter) throws IOException {
227229
if (iter.in == null) {
228230
return false;
229231
}
232+
if (iter.skipStartedAt != -1) {
233+
return keepSkippedBytesThenRead(iter);
234+
}
230235
int n = iter.in.read(iter.buf);
231236
if (n < 1) {
232237
if (n == -1) {
@@ -241,6 +246,34 @@ final static boolean loadMore(JsonIterator iter) throws IOException {
241246
return true;
242247
}
243248

249+
private static boolean keepSkippedBytesThenRead(JsonIterator iter) throws IOException {
250+
int n;
251+
int offset;
252+
if (iter.skipStartedAt == 0 || iter.skipStartedAt < iter.tail / 2) {
253+
byte[] newBuf = new byte[iter.buf.length * 2];
254+
offset = iter.tail - iter.skipStartedAt;
255+
System.arraycopy(iter.buf, iter.skipStartedAt, newBuf, 0, offset);
256+
iter.buf = newBuf;
257+
n = iter.in.read(iter.buf, offset, iter.buf.length - offset);
258+
} else {
259+
offset = iter.tail - iter.skipStartedAt;
260+
System.arraycopy(iter.buf, iter.skipStartedAt, iter.buf, 0, offset);
261+
n = iter.in.read(iter.buf, offset, iter.buf.length - offset);
262+
}
263+
iter.skipStartedAt = 0;
264+
if (n < 1) {
265+
if (n == -1) {
266+
return false;
267+
} else {
268+
throw iter.reportError("loadMore", "read from input stream returned " + n);
269+
}
270+
} else {
271+
iter.head = offset;
272+
iter.tail = offset + n;
273+
}
274+
return true;
275+
}
276+
244277
final static byte readByte(JsonIterator iter) throws IOException {
245278
if (iter.head == iter.tail) {
246279
if (!loadMore(iter)) {
@@ -249,4 +282,60 @@ final static byte readByte(JsonIterator iter) throws IOException {
249282
}
250283
return iter.buf[iter.head++];
251284
}
285+
286+
public static Any readAny(JsonIterator iter) throws IOException {
287+
iter.skipStartedAt = iter.head;
288+
byte c = IterImpl.nextToken(iter);
289+
switch (c) {
290+
case '"':
291+
IterImpl.skipString(iter);
292+
byte[] copied = copySkippedBytes(iter);
293+
return Any.lazyString(copied, 0, copied.length);
294+
case '-':
295+
case '0':
296+
case '1':
297+
case '2':
298+
case '3':
299+
case '4':
300+
case '5':
301+
case '6':
302+
case '7':
303+
case '8':
304+
case '9':
305+
IterImpl.skipUntilBreak(iter);
306+
copied = copySkippedBytes(iter);
307+
return Any.lazyNumber(copied, 0, copied.length);
308+
case 't':
309+
IterImpl.skipUntilBreak(iter);
310+
iter.skipStartedAt = -1;
311+
return Any.wrap(true);
312+
case 'f':
313+
IterImpl.skipUntilBreak(iter);
314+
iter.skipStartedAt = -1;
315+
return Any.wrap(false);
316+
case 'n':
317+
IterImpl.skipUntilBreak(iter);
318+
iter.skipStartedAt = -1;
319+
return Any.wrap((Object)null);
320+
case '[':
321+
IterImpl.skipArray(iter);
322+
copied = copySkippedBytes(iter);
323+
return Any.lazyArray(copied, 0, copied.length);
324+
case '{':
325+
IterImpl.skipObject(iter);
326+
copied = copySkippedBytes(iter);
327+
return Any.lazyObject(copied, 0, copied.length);
328+
default:
329+
throw iter.reportError("IterImplSkip", "do not know how to skip: " + c);
330+
}
331+
}
332+
333+
private static byte[] copySkippedBytes(JsonIterator iter) {
334+
int start = iter.skipStartedAt;
335+
iter.skipStartedAt = -1;
336+
int end = iter.head;
337+
byte[] bytes = new byte[end - start];
338+
System.arraycopy(iter.buf, start, bytes, 0, bytes.length);
339+
return bytes;
340+
}
252341
}

src/main/java/com/jsoniter/IterImplSkip.java

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,46 +18,6 @@ class IterImplSkip {
1818
breaks[']'] = true;
1919
}
2020

21-
public static final Any readAny(JsonIterator iter) throws IOException {
22-
int start = iter.head;
23-
byte c = IterImpl.nextToken(iter);
24-
switch (c) {
25-
case '"':
26-
IterImpl.skipString(iter);
27-
return Any.lazyString(iter.buf, start, iter.head);
28-
case '-':
29-
case '0':
30-
case '1':
31-
case '2':
32-
case '3':
33-
case '4':
34-
case '5':
35-
case '6':
36-
case '7':
37-
case '8':
38-
case '9':
39-
IterImpl.skipUntilBreak(iter);
40-
return Any.lazyNumber(iter.buf, start, iter.head);
41-
case 't':
42-
IterImpl.skipUntilBreak(iter);
43-
return Any.wrap(true);
44-
case 'f':
45-
IterImpl.skipUntilBreak(iter);
46-
return Any.wrap(false);
47-
case 'n':
48-
IterImpl.skipUntilBreak(iter);
49-
return Any.wrap((Object)null);
50-
case '[':
51-
IterImpl.skipArray(iter);
52-
return Any.lazyArray(iter.buf, start, iter.head);
53-
case '{':
54-
IterImpl.skipObject(iter);
55-
return Any.lazyObject(iter.buf, start, iter.head);
56-
default:
57-
throw iter.reportError("IterImplSkip", "do not know how to skip: " + c);
58-
}
59-
}
60-
6121
public static final void skip(JsonIterator iter) throws IOException {
6222
byte c = IterImpl.nextToken(iter);
6323
switch (c) {

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class JsonIterator implements Closeable {
2121
byte[] buf;
2222
int head;
2323
int tail;
24+
int skipStartedAt = -1; // skip should keep bytes starting at this pos
2425

2526
Map<String, Object> tempObjects = new HashMap<String, Object>();
2627
final Slice reusableSlice = new Slice(null, 0, 0);
@@ -260,10 +261,7 @@ public final BigInteger readBigInteger() throws IOException {
260261
}
261262

262263
public final Any readAny() throws IOException {
263-
if (in != null) {
264-
throw new JsonException("input can not be InputStream when readAny");
265-
}
266-
return IterImplSkip.readAny(this);
264+
return IterImpl.readAny(this);
267265
}
268266

269267
public final Object read() throws IOException {

src/test/java/com/jsoniter/TestReadAny.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22

33
import com.jsoniter.any.Any;
44
import junit.framework.TestCase;
5+
import org.junit.experimental.categories.Category;
56

7+
import java.io.ByteArrayInputStream;
68
import java.io.IOException;
9+
import java.util.ArrayList;
710
import java.util.Arrays;
811
import java.util.HashSet;
12+
import java.util.List;
913

1014
public class TestReadAny extends TestCase {
1115

@@ -162,4 +166,16 @@ public void test_require_path() throws IOException {
162166
System.out.println(e);
163167
}
164168
}
169+
170+
@Category(AllTests.StreamingCategory.class)
171+
public void test_read_any_in_streaming() throws IOException {
172+
assertEquals(2, JsonIterator.parse(new ByteArrayInputStream("[1,2,3,4,5]" .getBytes()), 2).readAny().toInt(1));
173+
assertEquals(1, JsonIterator.parse(new ByteArrayInputStream("{\"field1\": 1}" .getBytes()), 2).readAny().size());
174+
JsonIterator iter = JsonIterator.parse(new ByteArrayInputStream("[1,2,[3, 4],5]" .getBytes()), 2);
175+
ArrayList<Any> elements = new ArrayList<Any>();
176+
while(iter.readArray()) {
177+
elements.add(iter.readAny());
178+
}
179+
assertEquals("[3, 4]", elements.get(2).toString());
180+
}
165181
}

0 commit comments

Comments
 (0)