1414import io .sirix .axis .temporal .PrefetchedAllTimeAxis ;
1515import io .sirix .axis .temporal .PrefetchedFutureAxis ;
1616import io .sirix .axis .temporal .PrefetchedPastAxis ;
17+ import io .sirix .settings .Fixed ;
1718
1819import java .util .ArrayList ;
1920import java .util .List ;
@@ -39,6 +40,12 @@ public final class JsonDBArraySlice extends AbstractJsonDBArray<JsonDBArraySlice
3940 */
4041 private List <Sequence > values ;
4142
43+ /** Last slice-relative index served by {@link #at(int)} / {@link #at(IntNumeric)}. */
44+ private int cursorSliceIndex = -1 ;
45+
46+ /** Node key positioned at {@link #cursorSliceIndex}; {@link Fixed#NULL_NODE_KEY} if invalid. */
47+ private long cursorNodeKey = Fixed .NULL_NODE_KEY .getStandardProperty ();
48+
4249 /**
4350 * Constructor.
4451 *
@@ -59,13 +66,14 @@ public JsonDBArraySlice(final JsonNodeReadOnlyTrx rtx, final JsonDBCollection co
5966
6067 assert this .rtx .isArray ();
6168
62- jsonUtil = new JsonItemFactory ();
69+ jsonUtil = getJsonItemFactory ();
6370
64- if ((fromIndex < 0 ) || (fromIndex > toIndex ) || (fromIndex >= this .rtx .getChildCount ())) {
71+ final long childCount = this .rtx .getChildCount ();
72+ if ((fromIndex < 0 ) || (fromIndex > toIndex ) || (fromIndex >= childCount )) {
6573 throw new QueryException (ErrorCode .ERR_INVALID_ARGUMENT_TYPE , "Invalid array start index: %s" , fromIndex );
6674 }
6775
68- if (toIndex > this . rtx . getChildCount () ) {
76+ if (toIndex > childCount ) {
6977 throw new QueryException (ErrorCode .ERR_INVALID_ARGUMENT_TYPE , "Invalid array end index: %s" , toIndex );
7078 }
7179
@@ -117,55 +125,95 @@ public List<Sequence> values() {
117125 }
118126
119127 private List <Sequence > getValues () {
120- final var values = new ArrayList <Sequence >();
128+ final int length = toIndex - fromIndex ;
129+ final ArrayList <Sequence > out = new ArrayList <>(length );
130+ if (length == 0 ) {
131+ return out ;
132+ }
133+
134+ final ChildAxis axis = new ChildAxis (rtx );
121135
122- for (int i = 0 , length = len (); i < length ; i ++) {
123- values .add (at (fromIndex + i ));
136+ for (int skipped = 0 ; skipped < fromIndex ; skipped ++) {
137+ if (!axis .hasNext ()) {
138+ return out ;
139+ }
140+ axis .nextLong ();
124141 }
125142
126- return values ;
143+ for (int collected = 0 ; collected < length ; collected ++) {
144+ if (!axis .hasNext ()) {
145+ break ;
146+ }
147+ axis .nextLong ();
148+ out .add (jsonUtil .getSequence (rtx , collection ));
149+ }
150+
151+ invalidateCursor ();
152+ return out ;
127153 }
128154
129- private Sequence getSequenceAtIndex (final JsonNodeReadOnlyTrx rtx , final int index ) {
130- moveRtx ();
155+ private Sequence sequenceAtSliceIndex (final int sliceIndex ) {
156+ final int absoluteIndex = fromIndex + sliceIndex ;
157+ final long arrayKey = getNodeKey ();
131158
132- final var axis = new ChildAxis (rtx );
159+ if (cursorSliceIndex >= 0 && sliceIndex == cursorSliceIndex + 1
160+ && rtx .moveTo (cursorNodeKey ) && rtx .getParentKey () == arrayKey
161+ && rtx .hasRightSibling ()) {
162+ rtx .moveToRightSibling ();
163+ cursorSliceIndex = sliceIndex ;
164+ cursorNodeKey = rtx .getNodeKey ();
165+ return jsonUtil .getSequence (rtx , collection );
166+ }
133167
134- for ( int i = 0 ; i < index && axis . hasNext (); i ++)
135- axis . nextLong ( );
168+ moveRtx ();
169+ final ChildAxis axis = new ChildAxis ( rtx );
136170
137- if (axis .hasNext ()) {
171+ for (int i = 0 ; i < absoluteIndex ; i ++) {
172+ if (!axis .hasNext ()) {
173+ invalidateCursor ();
174+ return null ;
175+ }
138176 axis .nextLong ();
177+ }
139178
140- return jsonUtil .getSequence (rtx , collection );
179+ if (!axis .hasNext ()) {
180+ invalidateCursor ();
181+ return null ;
141182 }
183+ axis .nextLong ();
184+
185+ cursorSliceIndex = sliceIndex ;
186+ cursorNodeKey = rtx .getNodeKey ();
187+ return jsonUtil .getSequence (rtx , collection );
188+ }
142189
143- return null ;
190+ private void invalidateCursor () {
191+ cursorSliceIndex = -1 ;
192+ cursorNodeKey = Fixed .NULL_NODE_KEY .getStandardProperty ();
144193 }
145194
146195 @ Override
147- public Sequence at (IntNumeric numericIndex ) {
148- int ii = fromIndex + numericIndex .intValue ();
149- if (ii >= toIndex ) {
150- throw new QueryException (ErrorCode .ERR_INVALID_ARGUMENT_TYPE , "Invalid array index: %s" , numericIndex . intValue () );
196+ public Sequence at (final IntNumeric numericIndex ) {
197+ final int sliceIndex = numericIndex .intValue ();
198+ if (fromIndex + sliceIndex >= toIndex ) {
199+ throw new QueryException (ErrorCode .ERR_INVALID_ARGUMENT_TYPE , "Invalid array index: %s" , sliceIndex );
151200 }
152201
153202 if (values == null ) {
154- return getSequenceAtIndex ( rtx , ii );
203+ return sequenceAtSliceIndex ( sliceIndex );
155204 }
156205
157- return values .get (ii );
206+ return values .get (sliceIndex );
158207 }
159208
160209 @ Override
161- public Sequence at (int index ) {
162- int ii = fromIndex + index ;
163- if (ii >= toIndex ) {
210+ public Sequence at (final int index ) {
211+ if (fromIndex + index >= toIndex ) {
164212 throw new QueryException (ErrorCode .ERR_INVALID_ARGUMENT_TYPE , "Invalid array index: %s" , index );
165213 }
166214
167215 if (values == null ) {
168- return getSequenceAtIndex ( rtx , ii );
216+ return sequenceAtSliceIndex ( index );
169217 }
170218
171219 return values .get (index );
0 commit comments