private void MakeStack(ShaMapInner root, Hash256 index) { _inners = new LinkedList <ShaMapInner>(); var top = root; while (true) { _inners.AddLast(top); var existing = top.GetBranch(index); if (existing == null) { break; } if (existing.IsLeaf) { Leaf = existing.AsLeaf(); _matched = Leaf.Index.Equals(index); break; } if (existing.IsInner) { top = existing.AsInner(); } } }
// Descend into the tree, find the leaf matching this index // and if the tree has it. protected internal void SetLeaf(ShaMapLeaf leaf) { if (leaf.Version == -1) { leaf.Version = Version; } SetBranch(leaf.Index, leaf); }
public bool AddLeaf(ShaMapLeaf leaf) { var stack = PathToIndex(leaf.Index); if (stack.HasMatchedLeaf()) { return(false); } var top = stack.DirtyOrCopyInners(); top.AddLeafToTerminalInner(leaf); return(true); }
public bool UpdateLeaf(ShaMapLeaf leaf) { var stack = PathToIndex(leaf.Index); if (!stack.HasMatchedLeaf()) { return(false); } var top = stack.DirtyOrCopyInners(); // Why not update in place? Because of structural sharing top.SetLeaf(leaf); return(true); }
public void CollapseOnlyLeafChildInners() { Debug.Assert(_dirtied != null); ShaMapLeaf onlyChild = null; for (var i = _dirtied.Length - 1; i >= 0; i--) { var next = _dirtied[i]; if (onlyChild != null) { next.SetLeaf(onlyChild); } onlyChild = next.OnlyChildLeaf(); if (onlyChild == null) { break; } } }
/// <summary> /// This should only be called on the deepest inners, as it /// does not do any dirtying. </summary> /// <param name="leaf"> to add to inner </param> internal void AddLeafToTerminalInner(ShaMapLeaf leaf) { var branch = GetBranch(leaf.Index); if (branch == null) { SetLeaf(leaf); } else if (branch.IsInner) { throw new InvalidOperationException(); } else if (branch.IsLeaf) { var inner = MakeInnerChild(); SetBranch(leaf.Index, inner); inner.AddLeafToTerminalInner(leaf); inner.AddLeafToTerminalInner(branch.AsLeaf()); } }
/// <returns> the `only child` leaf or null if other children </returns> public ShaMapLeaf OnlyChildLeaf() { ShaMapLeaf leaf = null; var leaves = 0; foreach (var branch in Branches.Where(branch => branch != null)) { if (branch.IsInner) { leaf = null; break; } if (++leaves == 1) { leaf = branch.AsLeaf(); } else { leaf = null; break; } } return(leaf); }