package org.basex.query.expr; import static org.basex.query.QueryText.*; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.item.Empty; import org.basex.query.item.Item; import org.basex.query.item.Int; import org.basex.query.item.RangeSeq; import org.basex.query.item.SeqType; import org.basex.query.item.Value; import org.basex.query.iter.Iter; import org.basex.util.InputInfo; /** * Range expression. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public final class Range extends Arr { /** * Constructor. * @param ii input info * @param e1 first expression * @param e2 second expression */ public Range(final InputInfo ii, final Expr e1, final Expr e2) { super(ii, e1, e2); } @Override public Expr comp(final QueryContext ctx) throws QueryException { super.comp(ctx); Expr e = this; if(oneIsEmpty()) { e = Empty.SEQ; } else { final long[] v = range(ctx); if(v != null) { size = v[1] - v[0] + 1; // use iterative evaluation at runtime instead of range sequence // to avoid prevent intermediary result materialization e = size < 1 ? Empty.SEQ : size == 1 ? Int.get(v[0]) : this; } } type = SeqType.ITR_OM; return optPre(e, ctx); } @Override public Iter iter(final QueryContext ctx) throws QueryException { return value(ctx).iter(); } @Override public Value value(final QueryContext ctx) throws QueryException { final long[] v = rng(ctx); return v == null || v[0] > v[1] ? Empty.SEQ : v[0] == v[1] ? Int.get(v[0]) : new RangeSeq(v[0], v[1] - v[0] + 1); } /** * Returns the start and end value of the range operator, or {@code null} * if the range could not be evaluated. * @param ctx query context * @return value array * @throws QueryException query exception */ long[] range(final QueryContext ctx) throws QueryException { return allAreValues() ? rng(ctx) : null; } /** * Returns the start and end value of the range operator, or {@code null} * if the range could not be evaluated. * @param ctx query context * @return value array * @throws QueryException query exception */ private long[] rng(final QueryContext ctx) throws QueryException { final Item a = expr[0].item(ctx, input); if(a == null) return null; final Item b = expr[1].item(ctx, input); if(b == null) return null; return new long[] { checkItr(a), checkItr(b) }; } @Override public String toString() { return PAR1 + toString(' ' + TO + ' ') + PAR2; } }