@Override boolean instanceOf(final AtomType kt, final SeqType vt) { for (final TrieNode k : kids) { if (!(k == null || k.instanceOf(kt, vt))) return false; } return true; }
@Override boolean contains(final int h, final Item k, final int l, final InputInfo ii) throws QueryException { final int key = key(h, l); final TrieNode sub = kids[key]; return sub != null && sub.contains(h, k, l + 1, ii); }
@Override void forEach(final ValueBuilder vb, final FItem func, final QueryContext qc, final InputInfo ii) throws QueryException { for (final TrieNode nd : kids) { if (nd != null) nd.forEach(vb, func, qc, ii); } }
@Override TrieNode add(final TrieLeaf o, final int l, final InputInfo ii) throws QueryException { final int k = key(o.hash, l); final TrieNode ch = kids[k], nw; if (ch != null) { final TrieNode ins = ch.add(o, l + 1, ii); if (ins == ch) return this; nw = ins; } else nw = o; final TrieNode[] ks = copyKids(); ks[k] = nw; // we don't replace here, so the size must increase return new TrieBranch(ks, used | 1 << k, size + 1); }
@Override TrieNode add(final TrieBranch o, final int l, final InputInfo ii) throws QueryException { TrieNode[] ch = null; int nu = used, ns = size; final int kl = kids.length; for (int k = 0; k < kl; k++) { final TrieNode n = kids[k], ok = o.kids[k]; if (ok != null) { final TrieNode nw = n == null ? ok : ok.addAll(n, l + 1, ii); if (nw != n) { if (ch == null) ch = copyKids(); ch[k] = nw; nu |= 1 << k; ns += nw.size - (n == null ? 0 : n.size); } } } return ch == null ? this : new TrieBranch(ch, nu, ns); }
@Override TrieNode put(final int h, final Item k, final Value v, final int l, final InputInfo ii) throws QueryException { final int key = key(h, l); final TrieNode sub = kids[key], nsub; final int bs, rem; if (sub != null) { nsub = sub.put(h, k, v, l + 1, ii); if (nsub == sub) return this; bs = used; rem = sub.size; } else { nsub = new TrieLeaf(h, k, v); bs = used | 1 << key; rem = 0; } final TrieNode[] ks = copyKids(); ks[key] = nsub; return new TrieBranch(ks, bs, size - rem + nsub.size); }
@Override TrieNode delete(final int h, final Item k, final int l, final InputInfo ii) throws QueryException { final int key = key(h, l); final TrieNode sub = kids[key]; if (sub == null) return this; final TrieNode nsub = sub.delete(h, k, l + 1, ii); if (nsub == sub) return this; final int nu; if (nsub == null) { nu = used ^ 1 << key; if (Integer.bitCount(nu) == 1) { final TrieNode single = kids[Integer.numberOfTrailingZeros(nu)]; // check whether the child depends on the right offset if (!(single instanceof TrieBranch)) return single; } } else nu = used; final TrieNode[] ks = copyKids(); ks[key] = nsub; return new TrieBranch(ks, nu, size - 1); }
@Override Value get(final int h, final Item k, final int l, final InputInfo ii) throws QueryException { final int key = key(h, l); final TrieNode sub = kids[key]; return sub == null ? null : sub.get(h, k, l + 1, ii); }
@Override int hash(final InputInfo ii) throws QueryException { int hash = 0; for (final TrieNode ch : kids) if (ch != null) hash = 31 * hash + ch.hash(ii); return hash; }
@Override void values(final ValueBuilder vs) { for (final TrieNode nd : kids) if (nd != null) nd.values(vs); }
@Override void keys(final ValueBuilder ks) { for (final TrieNode nd : kids) if (nd != null) nd.keys(ks); }
@Override TrieNode addAll(final TrieNode o, final int l, final InputInfo ii) throws QueryException { return o.add(this, l, ii); }
@Override void materialize(final InputInfo ii) throws QueryException { for (final TrieNode nd : kids) { if (nd != null) nd.materialize(ii); } }