package org.basex.query.path; import static org.basex.query.util.Err.*; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.item.ANode; import org.basex.query.item.Value; import org.basex.query.iter.AxisIter; import org.basex.query.iter.NodeIter; /** * Iterative step expression with numeric predicates. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ final class IterPosStep extends AxisStep { /** * Constructor. * @param s step reference */ IterPosStep(final AxisStep s) { super(s.input, s.axis, s.test, s.preds); last = s.last; pos = s.pos; } @Override public NodeIter iter(final QueryContext ctx) { return new NodeIter() { boolean skip; AxisIter ai; long cpos; @Override public ANode next() throws QueryException { if(skip) return null; if(ai == null) { final Value v = checkCtx(ctx); if(!v.type.isNode()) NODESPATH.thrw(input, IterPosStep.this, v.type); ai = axis.iter((ANode) v); } ANode lnode = null, node; while(true) { ctx.checkStop(); node = ai.next(); if(node == null) { skip = last; return lnode; } // evaluate node test if(!test.eval(node)) continue; // evaluate predicates final long cp = ctx.pos; final long cs = ctx.size; ctx.size = 0; ctx.pos = ++cpos; final boolean p = preds(node, ctx); ctx.pos = cp; ctx.size = cs; if(p) { // check if more results can be expected skip = pos != null && pos.skip(ctx); return node.finish(); } // remember last node if(last) lnode = node.finish(); } } @Override public boolean reset() { ai = null; skip = false; cpos = 0; return true; } }; } }