All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.deephaven.engine.rowset.impl.rsp.container.RunContainerRangeIterator Maven / Gradle / Ivy

package io.deephaven.engine.rowset.impl.rsp.container;

import static io.deephaven.engine.rowset.impl.rsp.container.ContainerUtil.toIntUnsigned;

final class RunContainerRangeIterator implements SearchRangeIterator {
    private final RunContainer parent;

    private int pos;
    private int start;
    private int end; // end == -1 marks a just initialized iterator for which hasNext()/next() have not been called yet.

    RunContainerRangeIterator(final RunContainer p) {
        this(p, 0);
    }

    RunContainerRangeIterator(final RunContainer p, final int initialSkipCount) {
        pos = 0;
        parent = p;
        end = -1;
        final int numRuns = parent.numberOfRuns();
        if (numRuns == 0) {
            return;
        }
        if (initialSkipCount == 0) {
            start = runStart(pos);
            return;
        }
        int remaining = initialSkipCount;
        while (true) {
            int runSize = toIntUnsigned(parent.getLength(pos)) + 1;
            if (remaining < runSize) {
                start = runStart(pos) + remaining;
                break;
            }
            remaining -= runSize;
            ++pos;
            if (pos >= numRuns) {
                break;
            }
        }
    }

    RunContainerRangeIterator(final RunContainerRangeIterator other) {
        this.pos = other.pos;
        this.start = other.start;
        this.end = other.end;
        this.parent = other.parent;
    }

    public RunContainerRangeIterator copy() {
        return new RunContainerRangeIterator(this);
    }

    @Override
    public boolean hasNext() {
        if (end == -1) {
            return pos < parent.nbrruns;
        }
        return pos + 1 < parent.nbrruns;
    }

    private int runStart(final int i) {
        return toIntUnsigned(parent.getValue(i));
    }

    @Override
    public int start() {
        return start;
    }

    private int runLast(final int i) {
        return runLast(runStart(i), i);
    }

    private int runLast(final int runStart, final int i) {
        return runStart + toIntUnsigned(parent.getLength(i));
    }

    @Override
    public int end() {
        return end;
    }

    @Override
    public void next() {
        if (end == -1) {
            end = runLast(pos) + 1;
            return;
        }
        ++pos;
        start = runStart(pos);
        end = runLast(start, pos) + 1;
    }

    @Override
    public int next(final short[] buffer, final int offset, final int maxRanges) {
        int count = 0;
        if (end == -1 && maxRanges > 0) {
            buffer[offset] = (short) start;
            final int e = runLast(pos);
            buffer[offset + 1] = (short) e;
            ++count;
            if (pos + 1 >= parent.nbrruns || maxRanges < 2) {
                end = e + 1;
                return 1;
            }
        } else if (maxRanges <= 0) {
            return 0;
        }
        int s;
        int e;
        do {
            ++pos;
            s = runStart(pos);
            e = runLast(s, pos);
            buffer[offset + 2 * count] = (short) s;
            buffer[offset + 2 * count + 1] = (short) e;
            ++count;
        } while (count < maxRanges && pos + 1 < parent.nbrruns);
        start = s;
        end = e + 1;
        return count;
    }

    @Override
    public boolean advance(final int v) {
        if (end == -1) {
            if (!hasNext()) {
                return false;
            }
            next();
        }
        if (end - 1 >= v) {
            start = Math.max(start, v);
            return true;
        }
        int left = Math.max(0, pos);
        int right = parent.nbrruns - 1;
        if (runLast(right) < v) {
            pos = parent.nbrruns;
            return false;
        }
        // binary search over end elements.
        while (true) {
            pos = (left + right) / 2;
            if (runLast(pos) < v) {
                left = pos + 1;
            } else {
                if (right == pos) {
                    final int runStart = runStart(pos);
                    start = Math.max(runStart, v);
                    end = runLast(runStart, pos) + 1;
                    return true;
                }
                right = pos;
            }
        }
    }

    @Override
    public boolean search(final ContainerUtil.TargetComparator comp) {
        if (end == -1) {
            if (!hasNext()) {
                return false;
            }
            next();
        }
        if (comp.directionFrom(start) < 0) {
            return false;
        }
        int posStart = start;
        // we know comp.directionFrom(start) >= 0.
        int right = parent.nbrruns - 1;
        // 32 in the next line matches a cache line in shorts.
        // Note that since we don't know where in cache line boundaries
        // pos and right are, their range may span at most 2.
        while (pos + 32 < right) {
            final int mid = (pos + right) / 2;
            final int midStart = runStart(mid);
            final int c = comp.directionFrom(midStart);
            if (c < 0) {
                right = mid - 1;
                continue;
            }
            pos = mid;
            posStart = midStart;
        }
        // we finish the job with a sequential search.
        while (pos < right) {
            final int posNext = pos + 1;
            final int posNextStart = runStart(posNext);
            final int c = comp.directionFrom(posNextStart);
            if (c < 0) {
                break;
            }
            pos = posNext;
            posStart = posNextStart;
        }
        end = runLast(pos) + 1;
        start = ContainerUtil.rangeSearch(posStart, end, comp);
        assert (start != -1);
        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy