public void NodeAdded(AListNode <K, T> child, AListInnerBase <K, T> parent) { if (_nodes == null) { _nodes = new BMultiMap <AListNode <K, T>, AListInnerBase <K, T> >(CompareNodeHashCodes, CompareInnerHashCodes); } _nodes.Add(new KeyValuePair <AListNode <K, T>, AListInnerBase <K, T> >(child, parent)); }
protected AListInnerBase(AListInnerBase <K, T> frozen) { _children = InternalList.CopyToNewArray(frozen._children); _childCount = frozen._childCount; _maxNodeSize = frozen._maxNodeSize; _isFrozen = false; MarkChildrenFrozen(); AssertValid(); }
public void NodeRemoved(AListNode <K, T> child, AListInnerBase <K, T> parent) { int index = _nodes.IndexOfExact(new KeyValuePair <AListNode <K, T>, AListInnerBase <K, T> >(child, parent)); if (index <= -1) { BadState(); } _nodes.RemoveAt(index); }
/// <summary>Checks whether 'node' is frozen and if so, replaces it with an unfrozen copy.</summary> /// <param name="node">A node that the caller needs to be unfrozen</param> /// <param name="parent">Parent node (used by tob)</param> /// <param name="tob">Tree observer (null if none)</param> /// <returns>True if the node was unfrozen</returns> public static bool AutoClone(ref AListNode <K, T> node, AListInnerBase <K, T> parent, IAListTreeObserver <K, T> tob) { bool result = node.IsFrozen; if (result) { var old = node; node = node.DetachedClone(); if (tob != null) { tob.HandleChildReplaced(old, node, null, parent); } Debug.Assert(!node.IsFrozen); } return(result); }
protected AListInnerBase(AListInnerBase <K, T> original, int localIndex, int localCount, uint baseIndex, int maxNodeSize) { // round up size to the nearest 4. _children = new Entry[(localCount + 3) & ~3]; int i; for (i = 0; i < localCount; i++) { _children[i] = original._children[localIndex + i]; _children[i].Index -= baseIndex; } _childCount = (byte)localCount; Debug.Assert(maxNodeSize <= MaxMaxNodeSize); MaxNodeSize = maxNodeSize; InitEmpties(i); AssertValid(); }
/// <summary>Appends or prepends some other list to this list. The other /// list must be the same height or less tall.</summary> /// <param name="other">A list to append/prepend</param> /// <param name="heightDifference">Height difference between the trees (0 or >0)</param> /// <param name="splitRight">Right half in case node is split</param> /// <param name="tob">Observer to be notified of changes</param> /// <param name="move">Move semantics (avoids freezing the nodes of the other tree)</param> /// <param name="append">Operation to perform (true => append)</param> /// <returns>Normally null, or left half in case node is split</returns> public virtual AListInnerBase <T, T> Combine(AListInnerBase <T, T> other, int heightDifference, out AListNode <T, T> splitRight, IAListTreeObserver <T, T> tob, bool move, bool append) { Debug.Assert(!IsFrozen && heightDifference >= 0); if (heightDifference != 0) { int i = append ? LocalCount - 1 : 0; AutoClone(ref _children[i].Node, this, tob); var splitLeft = ((AListInner <T>)Child(i)).Combine(other, heightDifference - 1, out splitRight, tob, move, append); if (!append) { Debug.Assert(LocalCount == 1 || other.TotalCount == _children[0].Node.TotalCount - _children[1].Index); AdjustIndexesAfter(i, (int)other.TotalCount); } return(AutoHandleChildSplit(i, splitLeft, ref splitRight, tob)); } Debug.Assert(other.GetType() == GetType()); int otherLC = other.LocalCount; AutoEnlargeChildren(otherLC); for (int i = 0; i < otherLC; i++) { var child = other.Child(i); if (!move) { child.Freeze(); // we're sharing this node between two trees } if (append) { uint tc = TotalCount; LLInsert(_childCount, child, 0); _children[_childCount - 1].Index = tc; } else { LLInsert(i, child, child.TotalCount); } } return(AutoSplit(out splitRight)); }
protected AListInnerBase(AListInnerBase <K, T> original, uint index, uint count, AListBase <K, T> list) { // This constructor is called by CopySection Debug.Assert(count > 0 && count <= original.TotalCount); int i0 = original.BinarySearchI(index); int iN = original.BinarySearchI(index + count - 1); Entry e0 = original._children[i0]; Entry eN = original._children[iN]; int localCount = iN - i0 + 1; // round up size to the nearest 4. _children = new Entry[(localCount + 3) & ~3]; _isFrozen = false; _maxNodeSize = original._maxNodeSize; //_userByte = original._userByte; _childCount = (byte)localCount; InitEmpties(iN - i0 + 1); if (i0 == iN) { _children[0].Node = e0.Node.CopySection(index - e0.Index, count, list); } else { uint adjusted0 = index - e0.Index; uint adjustedN = index + count - eN.Index; Debug.Assert(adjusted0 <= index && adjustedN < count); AListNode <K, T> child0 = e0.Node.CopySection(adjusted0, e0.Node.TotalCount - adjusted0, list); AListNode <K, T> childN = eN.Node.CopySection(0, adjustedN, list); _children[0].Node = child0; _children[iN - i0].Node = childN; uint offset = child0.TotalCount; for (int i = i0 + 1; i < iN; i++) { AListNode <K, T> childI = original._children[i].Node; // Freeze child because it will be shared between the original // list and the section being copied childI.Freeze(); _children[i - i0] = new Entry { Node = childI, Index = offset }; offset += childI.TotalCount; } _children[iN - i0].Index = offset; // Finally, if the first/last node is undersized, redistribute items. // Note: we can set the 'tob' parameter to null because this // constructor is called by CopySection, which creates an // independent AList that does not have an indexer. while (_childCount > 1 && _children[0].Node.IsUndersized) { HandleUndersized(0, null); } while (_childCount > 1 && _children[_childCount - 1].Node.IsUndersized) { HandleUndersized(_childCount - 1, null); } } AssertValid(); }
internal static void HandleChildReplaced <K, T>(this IAListTreeObserver <K, T> self, AListNode <K, T> oldNode, AListNode <K, T> newLeft, AListNode <K, T> newRight, AListInnerBase <K, T> parent) { self.HandleNodeReplaced(oldNode, newLeft, newRight); if (parent != null) { self.NodeRemoved(oldNode, parent); self.NodeAdded(newLeft, parent); if (newRight != null) { self.NodeAdded(newRight, parent); } } }
internal static void HandleRootUnsplit <K, T>(this IAListTreeObserver <K, T> self, AListInnerBase <K, T> oldRoot, AListNode <K, T> newRoot) { Debug.Assert(oldRoot.LocalCount == 0 || (oldRoot.LocalCount == 1 && oldRoot.Child(0) == newRoot)); self.NodeRemoved(newRoot, oldRoot); self.RootChanged(newRoot, false); }
internal static void HandleRootSplit <K, T>(this IAListTreeObserver <K, T> self, AListNode <K, T> oldRoot, AListNode <K, T> newLeft, AListNode <K, T> newRight, AListInnerBase <K, T> newRoot) { self.HandleNodeReplaced(oldRoot, newLeft, newRight); self.NodeAdded(newLeft, newRoot); self.NodeAdded(newRight, newRoot); self.RootChanged(newRoot, false); }
public static void NodeMoved <K, T>(this IAListTreeObserver <K, T> self, AListNode <K, T> child, AListInnerBase <K, T> oldParent, AListInnerBase <K, T> newParent) { self.NodeRemoved(child, oldParent); self.NodeAdded(child, newParent); }