/* * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, * Version 1.0, and under the Eclipse Public License, Version 1.0 * (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.dev.store.btree; import java.util.ArrayList; import java.util.Iterator; /** * A cursor to iterate over elements in ascending order. * * @param <K> the key type * @param <V> the value type */ public class Cursor<K, V> implements Iterator<K> { protected final MVMap<K, V> map; protected final Page root; protected final K from; protected ArrayList<CursorPos> parents; protected CursorPos currentPos; protected K current; Cursor(MVMap<K, V> map, Page root, K from) { this.map = map; this.root = root; this.from = from; } public K next() { if (!hasNext()) { return null; } K c = current; if (c != null) { fetchNext(); } return c == null ? null : c; } /** * Fetch the next key. */ @SuppressWarnings("unchecked") protected void fetchNext() { current = (K) map.nextKey(currentPos, this); } public boolean hasNext() { if (parents == null) { // not initialized yet: fetch the first key parents = new ArrayList<CursorPos>(); currentPos = min(root, from); if (currentPos != null) { fetchNext(); } } return current != null; } public void remove() { throw new UnsupportedOperationException(); } /** * Add a cursor position to the stack. * * @param p the cursor position */ public void push(CursorPos p) { parents.add(p); } /** * Remove the latest cursor position from the stack and return it. * * @return the cursor position, or null if none */ public CursorPos pop() { int size = parents.size(); return size == 0 ? null : parents.remove(size - 1); } /** * Visit the first key that is greater or equal the given key. * * @param p the page * @param from the key, or null * @return the cursor position */ public CursorPos min(Page p, K from) { return map.min(p, this, from); } /** * Visit the first key within this child page. * * @param p the page * @param childIndex the child index * @return the cursor position */ public CursorPos visitChild(Page p, int childIndex) { p = p.getChildPage(childIndex); currentPos = min(p, null); return currentPos; } }