1111class ArrayLazyAny extends LazyAny {
1212
1313 private List <Any > cache ;
14+ private int lastParsedPos ;
1415
1516 public ArrayLazyAny (byte [] data , int head , int tail ) {
1617 super (data , head , tail );
@@ -44,15 +45,17 @@ public int size() {
4445
4546 @ Override
4647 public Iterator <Any > iterator () {
47- fillCache ();
48- return new ArrayIterator (cache );
48+ if (lastParsedPos == tail ) {
49+ return cache .iterator ();
50+ } else {
51+ return new LazyIterator (new JsonIterator ());
52+ }
4953 }
5054
5155 @ Override
5256 public Any get (int index ) {
5357 try {
54- fillCache ();
55- return cache .get (index );
58+ return fillCache (index );
5659 } catch (IndexOutOfBoundsException e ) {
5760 return null ;
5861 } catch (ClassCastException e ) {
@@ -65,8 +68,7 @@ public Any get(Object[] keys, int idx) {
6568 if (idx == keys .length ) {
6669 return this ;
6770 }
68- fillCache ();
69- return cache .get ((Integer ) keys [idx ]).get (keys , idx +1 );
71+ return fillCache ((Integer ) keys [idx ]).get (keys , idx + 1 );
7072 }
7173
7274 @ Override
@@ -76,43 +78,73 @@ public Any require(Object[] keys, int idx) {
7678 }
7779 Any result = null ;
7880 try {
79- fillCache ();
80- result = cache .get ((Integer ) keys [idx ]);
81+ result = fillCache ((Integer ) keys [idx ]);
8182 } catch (IndexOutOfBoundsException e ) {
8283 reportPathNotFound (keys , idx );
8384 }
8485 return result .require (keys , idx + 1 );
8586 }
8687
8788 private void fillCache () {
88- if (cache != null ) {
89+ if (lastParsedPos == tail ) {
8990 return ;
9091 }
91- try {
92- JsonIterator iter = parse ();
93- cache = new ArrayList <Any >(4 );
94- if (!CodegenAccess .readArrayStart (iter )) {
95- return ;
96- }
97- cache .add (iter .readAny ());
98- while (CodegenAccess .nextToken (iter ) == ',' ) {
99- cache .add (iter .readAny ());
100- }
101- } catch (IOException e ) {
102- throw new JsonException (e );
92+ LazyIterator iter = new LazyIterator (JsonIterator .tlsIter .get ());
93+ while (iter .hasNext ()) {
94+ // cache will be filled in the process
95+ iter .next ();
10396 }
10497 }
10598
106- private static class ArrayIterator implements Iterator <Any > {
99+ private Any fillCache (int target ) {
100+ if (lastParsedPos == tail ) {
101+ return cache .get (target );
102+ }
103+ int i = 0 ;
104+ LazyIterator iter = new LazyIterator (JsonIterator .tlsIter .get ());
105+ while (iter .hasNext ()) {
106+ Any element = iter .next ();
107+ if (i == target ) {
108+ return element ;
109+ }
110+ i ++;
111+ }
112+ throw new IndexOutOfBoundsException ();
113+ }
107114
108- private final int size ;
109- private final List <Any > array ;
110- private int idx ;
115+ private class LazyIterator implements Iterator <Any > {
116+
117+ private JsonIterator jsonIter ;
118+ private final int cacheSize ;
119+ private int cachePos ;
120+
121+ public LazyIterator (JsonIterator jsonIter ) {
122+ try {
123+ if (jsonIter != null ) {
124+ this .jsonIter = jsonIter ;
125+ this .jsonIter .reset (data , lastParsedPos , tail );
126+ }
127+ if (cache == null ) {
128+ cache = new ArrayList <Any >(4 );
129+ }
130+ if (lastParsedPos == head ) {
131+ readHead (jsonIter );
132+ }
133+ } catch (IOException e ) {
134+ throw new JsonException (e );
135+ }
136+ cacheSize = cache .size ();
137+ cachePos = 0 ;
138+ }
111139
112- public ArrayIterator (List <Any > array ) {
113- size = array .size ();
114- this .array = array ;
115- idx = 0 ;
140+ private void readHead (JsonIterator jsonIter ) throws IOException {
141+ if (jsonIter == null ) {
142+ jsonIter = JsonIterator .tlsIter .get ();
143+ jsonIter .reset (data , lastParsedPos , tail );
144+ }
145+ if (!CodegenAccess .readArrayStart (jsonIter )) {
146+ lastParsedPos = tail ;
147+ }
116148 }
117149
118150 @ Override
@@ -122,12 +154,35 @@ public void remove() {
122154
123155 @ Override
124156 public boolean hasNext () {
125- return idx < size ;
157+ return cachePos != cacheSize || lastParsedPos != tail ;
126158 }
127159
128160 @ Override
129161 public Any next () {
130- return array .get (idx ++);
162+ try {
163+ return next_ ();
164+ } catch (IOException e ) {
165+ throw new JsonException (e );
166+ }
167+ }
168+
169+ private Any next_ () throws IOException {
170+ if (cachePos != cacheSize ) {
171+ return cache .get (cachePos ++);
172+ }
173+ JsonIterator iter = jsonIter ;
174+ if (iter == null ) {
175+ iter = JsonIterator .tlsIter .get ();
176+ iter .reset (data , lastParsedPos , tail );
177+ }
178+ Any element = iter .readAny ();
179+ cache .add (element );
180+ if (CodegenAccess .nextToken (iter ) == ',' ) {
181+ lastParsedPos = CodegenAccess .head (iter );
182+ } else {
183+ lastParsedPos = tail ;
184+ }
185+ return element ;
131186 }
132187 }
133188}
0 commit comments