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); }
internal static void DoAttach <K, T>(this IAListTreeObserver <K, T> observer, AListNode <K, T> root, AListBase <K, T> list) { observer.Attach(list, childrenFirst => { observer.RootChanged(root, false); if (root != null) { AddAllRecursively(observer, childrenFirst, root); } }); }
private static void AddAllRecursively <K, T>(IAListTreeObserver <K, T> observer, bool childrenFirst, AListNode <K, T> node) { if (!childrenFirst) { observer.AddAll(node); } var inner = node as AListInnerBase <K, T>; if (inner != null) { for (int i = 0; i < inner.LocalCount; i++) { AddAllRecursively(observer, childrenFirst, inner.Child(i)); } } if (childrenFirst) { observer.AddAll(node); } }
protected override AListInnerBase <K, KeyValuePair <K, V> > SplitAt(int divAt, out AListNode <K, KeyValuePair <K, V> > right) { right = new BDictionaryInner <K, V>(this, divAt, LocalCount - divAt, _children[divAt].Index, MaxNodeSize); return(new BDictionaryInner <K, V>(this, 0, divAt, 0, MaxNodeSize)); }
protected K GetHighestKey(AListNode <K, T> node) { return(GetKey(node.GetLastItem())); }
/// <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)); }
public BDictionaryInner(AListNode <K, KeyValuePair <K, V> > left, AListNode <K, KeyValuePair <K, V> > right, int maxNodeSize) : base(left, right, maxNodeSize) { }
public override int DoSingleOperation(ref AListSingleOperation <K, T> op, out AListNode <K, T> splitLeft, out AListNode <K, T> splitRight) { Debug.Assert(!IsFrozen || op.Mode == AListOperation.Retrieve); AssertValid(); var tob = GetObserver(op.List); int i = BinarySearchK(op.Key, op.CompareKeys); if (op.Mode != AListOperation.Retrieve) { AutoClone(ref _children[i].Node, this, tob); if (op.Mode >= AListOperation.Add && _children[i].Node.IsFullLeaf) { TryToShiftAnItemToSiblingOfLeaf(i, tob); // Binary search result might now be off-by-1 i = BinarySearchK(op.Key, op.CompareKeys); } } AssertValid(); op.BaseIndex += _children[i].Index; int sizeChange = _children[i].Node.DoSingleOperation(ref op, out splitLeft, out splitRight); if (sizeChange != 0) { AdjustIndexesAfter(i, sizeChange); } // Handle child split / undersized / highest key changed if (splitLeft != null) { if (splitRight != null) { splitLeft = HandleChildSplit(i, splitLeft, ref splitRight, tob); } else { // Node is undersized and/or highest key changed bool flagParent = false; if (op.AggregateChanged != 0) { if (i < _childCount - 1) { _highestKey[i] = op.AggregateKey; op.AggregateChanged = 0; } else { // Update highest key in parent node instead flagParent = true; } } if (splitLeft.IsUndersized) { flagParent |= HandleUndersized(i, tob); } if (flagParent) { splitLeft = this; } else { splitLeft = null; } } } AssertValid(); return(sizeChange); }
public BListInner(AListNode <K, T> left, AListNode <K, T> right, int maxNodeSize) : base(left, right, maxNodeSize) { _highestKey = new K[_children.Length - 1]; _highestKey[0] = GetHighestKey(left); }
/// <summary>Called by DoSingleOperation to split a full node, then retry the add operation.</summary> /// <remarks>Same arguments and return value as DoSingleOperation.</remarks> protected virtual int SplitAndAdd(ref AListSingleOperation <K, T> op, out AListNode <K, T> splitLeft, out AListNode <K, T> splitRight) { // Tell DoSingleOperation not to send notifications to the observer op.AggregateChanged |= 2; int divAt = _list.Count >> 1; var mid = _list[divAt]; var left = new BListLeaf <K, T>(_maxNodeSize, _list.CopySection(0, divAt)); var right = new BListLeaf <K, T>(_maxNodeSize, _list.CopySection(divAt, _list.Count - divAt)); int sizeChange; if (op.CompareToKey(mid, op.Key) >= 0) { sizeChange = left.DoSingleOperation(ref op, out splitLeft, out splitRight); } else { op.BaseIndex += left.TotalCount; sizeChange = right.DoSingleOperation(ref op, out splitLeft, out splitRight); } op.AggregateChanged &= unchecked ((byte)~2); // (splitLeft may be non-null, meaning that the highest key changed, which doesn't matter here.) Debug.Assert(splitRight == null); Debug.Assert(sizeChange == 1); splitLeft = left; splitRight = right; return(sizeChange); }
public override int DoSingleOperation(ref AListSingleOperation <K, T> op, out AListNode <K, T> splitLeft, out AListNode <K, T> splitRight) { T searchItem = op.Item; int index = _list.BinarySearch(op.Key, op.CompareToKey, op.LowerBound); if (op.Found = (index >= 0)) { op.Item = _list[index]; // save old value if (op.RequireExactMatch && (searchItem == null ? op.Item == null : !searchItem.Equals(op.Item))) { op.Found = false; } } else { index = ~index; } splitLeft = splitRight = null; op.BaseIndex += (uint)index; if (op.Mode == AListOperation.Retrieve) { return(0); } if (op.Mode >= AListOperation.Add) { // Possible operations: Add, AddOrReplace, AddIfNotPresent, AddOrThrow if (_list.Count >= _maxNodeSize && (op.Mode == AListOperation.Add || !op.Found)) { op.BaseIndex -= (uint)index; op.Item = searchItem; return(SplitAndAdd(ref op, out splitLeft, out splitRight)); } if (op.Found && op.Mode != AListOperation.Add) { if (op.Mode == AListOperation.AddOrThrow) { throw new KeyAlreadyExistsException(); } else if (op.Mode == AListOperation.AddIfNotPresent) { return(0); } } else // add new item { if (HasListChanging(op.List)) { CallListChanging(op.List, new ListChangeInfo <T>(NotifyCollectionChangedAction.Add, (int)op.BaseIndex, 1, Iterable.Single(searchItem))); } if (index == _list.Count) { // Highest key may change splitLeft = this; op.AggregateChanged |= 1; op.AggregateKey = GetKey(op.List, searchItem); } _list.AutoRaiseCapacity(1, _maxNodeSize); _list.Insert(index, searchItem); if (GetObserver(op.List) != null) { if ((op.AggregateChanged & 2) == 0) { GetObserver(op.List).ItemAdded(searchItem, this); } } return(1); } Debug.Assert(op.Mode == AListOperation.AddOrReplace); } else if (op.Found) { // Possible operations: ReplaceIfPresent, Remove if (op.Mode == AListOperation.Remove) { if (HasListChanging(op.List)) { CallListChanging(op.List, new ListChangeInfo <T>(NotifyCollectionChangedAction.Remove, (int)op.BaseIndex, -1, null)); } _list.RemoveAt(index); if (index == _list.Count) { // Highest key may change splitLeft = this; if (_list.Count != 0) { op.AggregateChanged |= 1; op.AggregateKey = GetKey(op.List, _list.Last); } } else if (IsUndersized) { splitLeft = this; } if (GetObserver(op.List) != null) { Debug.Assert((op.AggregateChanged & 2) == 0); GetObserver(op.List).ItemRemoved(op.Item, this); } return(-1); } Debug.Assert(op.Mode == AListOperation.ReplaceIfPresent); } else { Debug.Assert(op.Mode == AListOperation.Remove || op.Mode == AListOperation.ReplaceIfPresent); return(0); // can't remove/replace because item was not found. } // Fallthrough action: replace existing item Debug.Assert(op.Found); if (HasListChanging(op.List)) { CallListChanging(op.List, new ListChangeInfo <T>(NotifyCollectionChangedAction.Replace, (int)op.BaseIndex, 0, Iterable.Single(searchItem))); } _list[index] = searchItem; if (index + 1 == _list.Count) { // Highest key may change splitLeft = this; op.AggregateChanged |= 1; op.AggregateKey = GetKey(op.List, searchItem); } if (GetObserver(op.List) != null) { GetObserver(op.List).ItemRemoved(op.Item, this); GetObserver(op.List).ItemAdded(searchItem, this); } return(0); }
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)); }
protected override AListInnerBase <T, T> SplitAt(int divAt, out AListNode <T, T> right) { right = new AListInner <T>(this, divAt, LocalCount - divAt, _children[divAt].Index, MaxNodeSize); return(new AListInner <T>(this, 0, divAt, 0, MaxNodeSize)); }
public AListInner(AListNode <T, T> left, AListNode <T, T> right, int maxNodeSize) : base(left, right, maxNodeSize) { }
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); }
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, 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); }
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)); }