/// <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)); }
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); }