/* * stack contains all ancestors of the node, stack.peek() is its parent. */ private void mutateUp(@NotNull final Deque<ChildReferenceTransient> stack, MutableNode node) { while (!stack.isEmpty()) { final ChildReferenceTransient parent = stack.pop(); final MutableNode mutableParent = parent.mutate(this); mutableParent.setChild(parent.firstByte, node); node = mutableParent; } }
@Override public boolean add(@NotNull final ByteIterable key, @NotNull final ByteIterable value) { final ByteIterator it = key.iterator(); NodeBase node = root; MutableNode mutableNode = null; final Deque<ChildReferenceTransient> stack = new ArrayDeque<>(); while (true) { final NodeBase.MatchResult matchResult = node.matchesKeySequence(it); final int matchingLength = matchResult.matchingLength; if (matchingLength < 0) { final MutableNode prefix = node.getMutableCopy(this).splitKey(-matchingLength - 1, matchResult.keyByte); if (matchResult.hasNext) { prefix.hang(matchResult.nextByte, it).setValue(value); } else { prefix.setValue(value); } if (stack.isEmpty()) { root = new MutableRoot(prefix, root.sourceAddress); } else { final ChildReferenceTransient parent = stack.pop(); mutableNode = parent.mutate(this); mutableNode.setChild(parent.firstByte, prefix); } break; } if (!it.hasNext()) { if (node.hasValue()) { return false; } mutableNode = node.getMutableCopy(this); mutableNode.setValue(value); break; } final byte nextByte = it.next(); final NodeBase child = node.getChild(this, nextByte); if (child == null) { mutableNode = node.getMutableCopy(this); if (mutableNode.hasChildren() || mutableNode.hasKey() || mutableNode.hasValue()) { mutableNode.hang(nextByte, it).setValue(value); } else { mutableNode.setKeySequence(new ArrayByteIterable(nextByte, it)); mutableNode.setValue(value); } break; } stack.push(new ChildReferenceTransient(nextByte, node)); node = child; } ++size; mutateUp(stack, mutableNode); TreeCursorMutable.notifyCursors(this); return true; }