Esempio n. 1
0
 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);
 }
Esempio n. 2
0
 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);
         }
     });
 }
Esempio n. 3
0
        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);
            }
        }
Esempio n. 4
0
 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));
 }
Esempio n. 5
0
 protected K GetHighestKey(AListNode <K, T> node)
 {
     return(GetKey(node.GetLastItem()));
 }
Esempio n. 6
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));
        }
Esempio n. 7
0
 public BDictionaryInner(AListNode <K, KeyValuePair <K, V> > left, AListNode <K, KeyValuePair <K, V> > right, int maxNodeSize) : base(left, right, maxNodeSize)
 {
 }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
 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);
 }
Esempio n. 10
0
        /// <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);
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
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));
 }
Esempio n. 13
0
 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));
 }
Esempio n. 14
0
 public AListInner(AListNode <T, T> left, AListNode <T, T> right, int maxNodeSize) : base(left, right, maxNodeSize)
 {
 }
Esempio n. 15
0
 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);
 }
Esempio n. 16
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));
        }
Esempio n. 17
0
 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);
 }
Esempio n. 18
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));
        }