internal static void Clear <K, T>(this IAListTreeObserver <K, T> self, AListBase <K, T> list) { self.RootChanged(list, null, true); }
internal static void ItemMoved <K, T>(this IAListTreeObserver <K, T> self, T item, AListLeaf <K, T> oldParent, AListLeaf <K, T> newParent) { self.ItemRemoved(item, oldParent); self.ItemAdded(item, newParent); }
public AListSparseOperation(uint index, bool isInsert, bool writeEmpty, int count, IAListTreeObserver <int, T> tob) { AbsoluteIndex = (uint)index; IsInsert = isInsert; WriteEmpty = writeEmpty; Item = default(T); SourceIndex = 0; Source = SparseSource = null; SourceCount = count; this.tob = tob; }
/// <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)); }
/// <summary>Takes an element from a right sibling.</summary> /// <returns>Returns the number of elements moved on success (1 if a leaf /// node, TotalCount of the child moved otherwise), or 0 if either (1) /// IsFullLeaf is true, or (2) one or both nodes is frozen.</returns> internal abstract uint TakeFromRight(AListNode <K, T> rightSibling, IAListTreeObserver <K, T> tob);
public static bool AutoClone(ref AListNode <K, T> node, AListInnerBase <K, T> parent, IAListTreeObserver <K, T> tob) { if (node.IsFrozen) { node = Clone(node, parent, tob); return(true); } return(false); }
/// <summary>Inserts a list of items at the specified index. This method /// may not insert all items at once, so there is a sourceIndex parameter /// which points to the next item to be inserted. When sourceIndex reaches /// source.Count, the insertion is complete.</summary> /// <param name="index">The index at which to insert the contents of /// source. Important: if sourceIndex > 0, insertion of the remaining /// items starts at [index + sourceIndex].</param> /// <returns>Returns non-null if the node is split, as explained /// in the documentation of <see cref="Insert"/>.</returns> /// <remarks>This method can only be called for ALists, since other tree /// types don't allow insertion at a specific index.</remarks> /// <exception cref="NotSupportedException">This node does not allow insertion at an arbitrary location (e.g. BList node).</exception> public virtual AListNode <K, T> InsertRange(uint index, IListSource <T> source, ref int sourceIndex, out AListNode <K, T> splitRight, IAListTreeObserver <K, T> tob) { throw new NotSupportedException(); }
/// <summary>Sets an item at the specified sub-index.</summary> /// <remarks>Currently, this method can be called for all tree types, even /// though improper use could break the tree invariant (e.g. sorted order of BList). /// </remarks> public abstract void SetAt(uint index, T item, IAListTreeObserver <K, T> tob);
internal override uint TakeFromLeft(AListNode <int, T> sibling, int localsToMove, IAListTreeObserver <int, T> tob) { Debug.Assert(localsToMove <= sibling.LocalCount && LocalCount + localsToMove <= _maxNodeSize); var left = (SparseAListLeaf <T>)sibling; if (_isFrozen || left._isFrozen) { return(0); } uint spaceBeingMoved; int startIndex = left._list.Count - localsToMove; // Be greedy: when taking all items, we must also take empty space before them uint startOffset = startIndex == 0 ? 0 : left._list[startIndex].Offset; spaceBeingMoved = left._totalCount - startOffset; AdjustOffsetsStartingAt(startIndex, ref left._list, -(int)startOffset); AdjustOffsetsStartingAt(0, ref _list, (int)spaceBeingMoved); var itemsToMove = left._list.Slice(left._list.Count - localsToMove, localsToMove); _list.InsertRange(0, itemsToMove); left._list.RemoveRange(startIndex, localsToMove); left._totalCount -= spaceBeingMoved; _totalCount += spaceBeingMoved; //if (tob != null) tob.ItemMoved(item, left, this); return(spaceBeingMoved); }
public override AListNode <int, T> Insert(uint index, T item, out AListNode <int, T> splitRight, IAListTreeObserver <int, T> tob) { throw new NotSupportedException(); }
internal override uint TakeFromRight(AListNode <int, T> sibling, int localsToMove, IAListTreeObserver <int, T> tob) { Debug.Assert(localsToMove <= sibling.LocalCount && LocalCount + localsToMove <= _maxNodeSize); var right = (SparseAListLeaf <T>)sibling; if (_isFrozen || right._isFrozen) { return(0); } uint spaceBeingMoved; int localStart = _list.Count; // Be greedy: when taking all items, we must also take empty space after them spaceBeingMoved = localsToMove == right._list.Count ? right.TotalCount : right._list[localsToMove].Offset; _list.AddRange(right._list.Slice(0, localsToMove)); right._list.RemoveRange(0, localsToMove); AdjustOffsetsStartingAt(localStart, ref _list, (int)_totalCount); AdjustOffsetsStartingAt(0, ref right._list, -(int)spaceBeingMoved); right._totalCount -= spaceBeingMoved; _totalCount += spaceBeingMoved; //if (tob != null) tob.ItemMoved(item, right, this); return(spaceBeingMoved); }
public override AListNode <T, T> Insert(uint index, T item, out AListNode <T, T> splitRight, IAListTreeObserver <T, T> tob) { Debug.Assert(!IsFrozen); Entry e; int i = PrepareToInsertAt(index, out e, tob); // Perform the insert, and adjust base index of nodes that follow AssertValid(); var splitLeft = e.Node.Insert(index - e.Index, item, out splitRight, tob); AdjustIndexesAfter(i, 1); // Handle child split return(splitLeft == null ? null : HandleChildSplit(i, splitLeft, ref splitRight, tob)); }
private AListInnerBase <T, T> AutoHandleChildSplit(int i, AListNode <T, T> splitLeft, ref AListNode <T, T> splitRight, IAListTreeObserver <T, T> tob) { if (splitLeft == null) { AssertValid(); return(null); } return(HandleChildSplit(i, splitLeft, ref splitRight, tob)); }
internal 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); }
protected new AListInnerBase <K, T> HandleChildSplit(int i, AListNode <K, T> splitLeft, ref AListNode <K, T> splitRight, IAListTreeObserver <K, T> tob) { // Update _highestKey. base.HandleChildSplit will call LLInsert // which will update _highestKey for the newly inserted right child, // but we must manually update the left child at _highestKey[i], // unless i == _childCount-1. if (i < _childCount - 1) { _highestKey[i] = GetHighestKey(splitLeft); } return(base.HandleChildSplit(i, splitLeft, ref splitRight, tob)); }
internal static void HandleRootUnsplit <K, T>(this IAListTreeObserver <K, T> self, AListBase <K, T> list, 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(list, newRoot, false); }
public override bool RemoveAt(uint index, uint count, IAListTreeObserver <K, T> tob) { return(base.RemoveAt(index, count, tob) || index == LocalCount); }
/// <summary>Removes an item at the specified index.</summary> /// <returns>Returns true if the node is undersized after the removal, or /// if this is an organized tree and the removal caused the aggregate key /// (highest key in a B+tree) to change.</returns> /// <remarks> /// When the node is undersized, but is not the root node, the parent will /// shift an item from a sibling, or discard the node and redistribute its /// children among existing nodes. If it is the root node, it is only /// discarded if it is an inner node with a single child (the child becomes /// the new root node), or it is a leaf node with no children. /// </remarks> public abstract bool RemoveAt(uint index, uint count, IAListTreeObserver <K, T> tob);
internal static void Clear <K, T>(this IAListTreeObserver <K, T> self) { self.RootChanged(null, true); }
/// <summary>Takes an element from a left sibling.</summary> /// <returns>Returns the number of elements moved on success (1 if a leaf /// node, TotalCount of the child moved otherwise), or 0 if either (1) /// IsFullLeaf is true, or (2) one or both nodes is frozen.</returns> internal abstract uint TakeFromLeft(AListNode <K, T> leftSibling, IAListTreeObserver <K, T> tob);
internal override uint TakeFromRight(AListNode <K, T> sibling, int localsToMove, IAListTreeObserver <K, T> tob) { Debug.Assert(localsToMove <= sibling.LocalCount && LocalCount + localsToMove <= _maxNodeSize); var right = (AListLeaf <K, T>)sibling; if (_isFrozen || right._isFrozen) { return(0); } EnsureCapacity(localsToMove); _list.AddRange(right._list.Slice(0, localsToMove)); right._list.RemoveRange(0, localsToMove); if (tob != null) { tob.ItemsMoved(_list, _list.Count - localsToMove, localsToMove, right, this); } return((uint)localsToMove); }
static AListNode <K, T> Clone(AListNode <K, T> node, AListInnerBase <K, T> parent, IAListTreeObserver <K, T> tob) { var clone = node.DetachedClone(); if (tob != null) { tob.HandleChildReplaced(node, clone, null, parent); } Debug.Assert(!clone.IsFrozen); return(clone); }
internal override uint TakeFromLeft(AListNode <K, T> sibling, int localsToMove, IAListTreeObserver <K, T> tob) { Debug.Assert(localsToMove <= sibling.LocalCount && LocalCount + localsToMove <= _maxNodeSize); var left = (AListLeaf <K, T>)sibling; if (_isFrozen || left._isFrozen) { return(0); } EnsureCapacity(localsToMove); int leftStart = left._list.Count - localsToMove; _list.InsertRange(0, left._list.Slice(leftStart, localsToMove)); left._list.RemoveRange(leftStart, localsToMove); if (tob != null) { tob.ItemsMoved(_list, 0, localsToMove, left, this); } return((uint)localsToMove); }
/// <summary>Inserts an item at the specified index. This method can only /// be called for ALists, since other tree types don't allow insertion at /// a specific index.</summary> /// <returns>Returns null if the insert completed normally. If the node /// split in half, the return value is the left side, and splitRight is /// set to the right side.</returns> /// <exception cref="NotSupportedException">This node does not allow insertion at an arbitrary location (e.g. BList node).</exception> public virtual AListNode <K, T> Insert(uint index, T item, out AListNode <K, T> splitRight, IAListTreeObserver <K, T> tob) { throw new NotSupportedException(); }
public override AListNode <T, T> InsertRange(uint index, IListSource <T> source, ref int sourceIndex, out AListNode <T, T> splitRight, IAListTreeObserver <T, T> tob) { Debug.Assert(!IsFrozen); Entry e; int i = PrepareToInsertAt(index + (uint)sourceIndex, out e, tob); // Perform the insert int oldSourceIndex = sourceIndex; AListNode <T, T> splitLeft; do { splitLeft = e.Node.InsertRange(index - e.Index, source, ref sourceIndex, out splitRight, tob); } while (sourceIndex < source.Count && splitLeft == null); // Adjust base index of nodes that follow int change = sourceIndex - oldSourceIndex; AdjustIndexesAfter(i, change); // Handle child split return(splitLeft == null ? null : HandleChildSplit(i, splitLeft, ref splitRight, tob)); }