| 19 | */ |
| 20 | public final class FnTrunk extends StandardFunc { |
| 21 | @Override |
| 22 | public Iter iter(final QueryContext qc) throws QueryException { |
| 23 | // retrieve and decrement iterator size |
| 24 | final Iter input = arg(0).iter(qc); |
| 25 | final long size = input.size(); |
| 26 | |
| 27 | // return empty iterator if iterator yields 0 or 1 items, or if result is an empty sequence |
| 28 | if(size == 0 || size == 1) return Empty.ITER; |
| 29 | |
| 30 | // check if iterator is value-based |
| 31 | if(input.valueIter()) return input.value(qc, null).subsequence(0, size - 1, qc).iter(); |
| 32 | |
| 33 | // return optimized iterator if result size is known |
| 34 | if(size != -1) return new Iter() { |
| 35 | int c; |
| 36 | |
| 37 | @Override |
| 38 | public Item next() throws QueryException { |
| 39 | return ++c < size ? qc.next(input) : null; |
| 40 | } |
| 41 | @Override |
| 42 | public Item get(final long i) throws QueryException { |
| 43 | return input.get(i); |
| 44 | } |
| 45 | @Override |
| 46 | public long size() { |
| 47 | return size - 1; |
| 48 | } |
| 49 | }; |
| 50 | |
| 51 | // otherwise, return standard iterator |
| 52 | return new Iter() { |
| 53 | Item last = input.next(); |
| 54 | |
| 55 | @Override |
| 56 | public Item next() throws QueryException { |
| 57 | final Item item = last; |
| 58 | if(item != null) { |
| 59 | last = input.next(); |
| 60 | if(last == null) return null; |
| 61 | } |
| 62 | return item; |
| 63 | } |
| 64 | }; |
| 65 | } |
| 66 | |
| 67 | @Override |
| 68 | public Value value(final QueryContext qc) throws QueryException { |