package org.basex.query.util; import java.util.Arrays; import java.util.Iterator; import org.basex.query.QueryException; import org.basex.query.item.Item; import org.basex.util.InputInfo; import org.basex.util.Util; /** * Set for quickly indexing items. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public final class ItemSet implements Iterable<Item> { /** Initial hash capacity. */ private static final int CAP = 1 << 3; /** Hash values. */ private int[] hash = new int[CAP]; /** Pointers to the next token. */ private int[] next = new int[CAP]; /** Hash table buckets. */ private int[] bucket = new int[CAP]; /** Hashed items. */ Item[] keys = new Item[CAP]; /** Hash entries. Actual hash size is {@code size - 1}. */ int size = 1; /** * Indexes the specified item. * @param ii input info * @param i item * @return true if value is new * @throws QueryException query exception */ public boolean index(final InputInfo ii, final Item i) throws QueryException { if(size == next.length) rehash(); final int h = i.hash(ii); final int p = h & bucket.length - 1; for(int id = bucket[p]; id != 0; id = next[id]) { if(keys[id].equiv(ii, i)) return false; } next[size] = bucket[p]; hash[size] = h; keys[size] = i; bucket[p] = size++; return true; } /** * Resizes the hash table. */ private void rehash() { final int s = size << 1; final int[] b = new int[s]; final int l = bucket.length; for(int i = 0; i < l; ++i) { int id = bucket[i]; while(id != 0) { final int p = hash[id] & s - 1; final int nx = next[id]; next[id] = b[p]; b[p] = id; id = nx; } } bucket = b; next = Arrays.copyOf(next, s); hash = Arrays.copyOf(hash, s); final Item[] i = new Item[s]; System.arraycopy(keys, 0, i, 0, size); keys = i; } /** * Returns the number of entries. * @return number of entries */ public int size() { return size - 1; } @Override public Iterator<Item> iterator() { return new Iterator<Item>() { private int c = 1; @Override public boolean hasNext() { return c < size; } @Override public Item next() { return keys[c++]; } @Override public void remove() { Util.notexpected(); } }; } }