2 * (C) Copyright 2017 Pantheon Technologies, s.r.o. and others.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.opendaylight.yangtools.triemap;
18 import static com.google.common.base.Preconditions.checkState;
20 import java.util.ArrayList;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map.Entry;
24 import java.util.NoSuchElementException;
26 class TrieMapIterator<K, V> implements Iterator<Entry<K, V>> {
28 protected TrieMap<K, V> ct;
29 private final boolean mustInit;
30 private final BasicNode[][] stack = new BasicNode[7][];
31 private final int[] stackpos = new int[7];
32 private int depth = -1;
33 private Iterator<Entry<K, V>> subiter = null;
34 private EntryNode<K, V> current = null;
35 private Entry<K, V> lastReturned = null;
37 TrieMapIterator (final int level, final TrieMap<K, V> ct, final boolean mustInit) {
40 this.mustInit = mustInit;
46 TrieMapIterator (final int level, final TrieMap<K, V> ct) {
47 this (level, ct, true);
52 public boolean hasNext() {
53 return (current != null) || (subiter != null);
57 public Entry<K, V> next() {
59 throw new NoSuchElementException();
63 if (subiter != null) {
73 final Entry<K, V> rr = r;
79 Entry<K, V> nextEntry(final Entry<K, V> rr) {
80 return new Entry<K, V>() {
81 @SuppressWarnings("null")
82 private V updated = null;
90 public V getValue () {
91 return (updated == null) ? rr.getValue (): updated;
95 public V setValue (final V value) {
97 return ct.replace (getKey (), value);
102 private void readin (final INode<K, V> in) {
103 MainNode<K, V> m = in.gcasRead (ct);
104 if (m instanceof CNode) {
105 CNode<K, V> cn = (CNode<K, V>) m;
107 stack [depth] = cn.array;
108 stackpos [depth] = -1;
110 } else if (m instanceof TNode) {
111 current = (TNode<K, V>) m;
112 } else if (m instanceof LNode) {
113 subiter = ((LNode<K, V>) m).iterator();
115 } else if (m == null) {
121 private void checkSubiter () {
122 if (!subiter.hasNext ()) {
130 // assert (ct.isReadOnly());
131 readin(ct.RDCSS_READ_ROOT());
136 int npos = stackpos [depth] + 1;
137 if (npos < stack [depth].length) {
138 stackpos [depth] = npos;
139 BasicNode elem = stack [depth] [npos];
140 if (elem instanceof SNode) {
141 current = (SNode<K, V>) elem;
142 } else if (elem instanceof INode) {
143 readin ((INode<K, V>) elem);
154 protected TrieMapIterator<K, V> newIterator(final int _lev, final TrieMap<K, V> _ct, final boolean _mustInit) {
155 return new TrieMapIterator<> (_lev, _ct, _mustInit);
158 protected void dupTo(final TrieMapIterator<K, V> it) {
159 it.level = this.level;
161 it.depth = this.depth;
162 it.current = this.current;
164 // these need a deep copy
165 System.arraycopy (this.stack, 0, it.stack, 0, 7);
166 System.arraycopy (this.stackpos, 0, it.stackpos, 0, 7);
168 // this one needs to be evaluated
169 if (this.subiter == null) {
172 List<Entry<K, V>> lst = toList (this.subiter);
173 this.subiter = lst.iterator ();
174 it.subiter = lst.iterator ();
178 // /** Returns a sequence of iterators over subsets of this iterator.
179 // * It's used to ease the implementation of splitters for a parallel
180 // version of the TrieMap.
182 // protected def subdivide(): Seq[Iterator[(K, V)]] = if (subiter ne
184 // // the case where an LNode is being iterated
190 // } else if (depth == -1) {
195 // while (d <= depth) {
196 // val rem = stack(d).length - 1 - stackpos(d)
198 // val (arr1, arr2) = stack(d).drop(stackpos(d) + 1).splitAt(rem / 2)
201 // val it = newIterator(level + 1, ct, false)
202 // it.stack(0) = arr2
203 // it.stackpos(0) = -1
205 // it.advance() // <-- fix it
207 // return Seq(this, it)
215 private List<Entry<K, V>> toList (final Iterator<Entry<K, V>> it) {
216 ArrayList<Entry<K, V>> list = new ArrayList<> ();
217 while (it.hasNext ()) {
218 list.add (it.next());
224 public void remove() {
225 checkState(lastReturned != null);
226 ct.remove(lastReturned.getKey());