Example #1
0
 internal static void Clear <K, T>(this IAListTreeObserver <K, T> self, AListBase <K, T> list)
 {
     self.RootChanged(list, null, true);
 }
Example #2
0
 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);
 }
Example #3
0
 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;
 }
Example #4
0
        /// <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));
        }
Example #5
0
 /// <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);
Example #6
0
 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);
 }
Example #7
0
 /// <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();
 }
Example #8
0
 /// <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);
Example #9
0
        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);
        }
Example #10
0
 public override AListNode <int, T> Insert(uint index, T item, out AListNode <int, T> splitRight, IAListTreeObserver <int, T> tob)
 {
     throw new NotSupportedException();
 }
Example #11
0
        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);
        }
Example #12
0
        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));
        }
Example #13
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));
 }
Example #14
0
 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);
 }
Example #15
0
        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));
        }
Example #16
0
 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);
 }
Example #17
0
 public override bool RemoveAt(uint index, uint count, IAListTreeObserver <K, T> tob)
 {
     return(base.RemoveAt(index, count, tob) || index == LocalCount);
 }
Example #18
0
 /// <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);
Example #19
0
 internal static void Clear <K, T>(this IAListTreeObserver <K, T> self)
 {
     self.RootChanged(null, true);
 }
Example #20
0
 /// <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);
Example #21
0
        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);
        }
Example #22
0
        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);
        }
Example #23
0
        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);
        }
Example #24
0
 /// <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();
 }
Example #25
0
        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));
        }