Example #1
0
        private int DoReplace(ref AListSparseOperation <T> op, int index, out AListNode <int, T> splitLeft, out AListNode <int, T> splitRight)
        {
            if (op.WriteEmpty)
            {
                int  i1, i2;
                uint leftToReplace = (uint)(op.SourceCount - op.SourceIndex);
                uint startAt       = (uint)(index + op.SourceIndex);
                i1 = GetSectionRange(startAt, leftToReplace, out i2);
                _list.RemoveRange(i1, i2 - i1);

                uint amtReplaced = System.Math.Min(leftToReplace, _totalCount - startAt);
                op.SourceIndex += (int)amtReplaced;

                splitLeft = splitRight = null;
                if (IsUndersized)
                {
                    splitLeft = this;
                }

                return(0);
            }

            // Currently there is only one other replacement operation exposed on
            // SparseAList, namely changing the value of a single item. I'll
            // include code for changing multiple items at once, but not optimize
            // that case. And no sparse support.
            Debug.Assert(op.SparseSource == null);

            splitLeft = splitRight = null;
            if (op.Source != null)
            {
                for (; op.SourceIndex < op.SourceCount; op.SourceIndex++)
                {
                    op.Item = op.Source[op.SourceIndex];
                    if (!ReplaceSingleItem(ref op, (uint)(index + op.SourceIndex)))
                    {
                        SplitLeaf(out splitLeft, out splitRight);
                        return(0);
                    }
                }
            }
            else
            {
                Debug.Assert(op.SourceIndex == 0 && op.SourceCount == 1);
                if (!ReplaceSingleItem(ref op, (uint)(index + op.SourceIndex)))
                {
                    SplitLeaf(out splitLeft, out splitRight);
                    return(0);
                }
                op.SourceIndex++;
            }
            return(0);
        }
Example #2
0
 internal override int DoSparseOperation(ref AListSparseOperation <T> op, int index, out AListNode <int, T> splitLeft, out AListNode <int, T> splitRight)
 {
     Debug.Assert(!IsFrozen);
     if (op.IsInsert)
     {
         return(DoInsert(ref op, index, out splitLeft, out splitRight));
     }
     else
     {
         return(DoReplace(ref op, index, out splitLeft, out splitRight));
     }
 }
Example #3
0
        private bool ReplaceSingleItem(ref AListSparseOperation <T> op, uint index)
        {
            int i;

            if (BinarySearch(index, out i))
            {
                _list.InternalArray[_list.Internalize(i)].Item = op.Item;
            }
            else
            {
                if (_list.Count >= _maxNodeSize)
                {
                    return(false);
                }
                _list.Insert(i, new Entry(index, op.Item));
            }
            return(true);
        }
Example #4
0
        internal override int DoSparseOperation(ref AListSparseOperation <T> op, int index, out AListNode <int, T> splitLeft, out AListNode <int, T> splitRight)
        {
            Debug.Assert(!IsFrozen);
            Debug.Assert(op.Source == null || op.SourceCount == op.Source.Count);
            AssertValid();
            Entry e = default(Entry);

            // Perform the insert/replace
            int change = 0, i = 0;

            do
            {
                if (change == 0)
                {
                    // runs once for insert operations, once or multiple times for replace
                    i = BinarySearchI((uint)(index + op.SourceIndex));
                    AutoClone(ref _children[i].Node, this, op.tob);
                    e = _children[i];
                }
                change += e.Node.DoSparseOperation(ref op, index - (int)e.Index, out splitLeft, out splitRight);
            } while (op.SourceIndex < op.SourceCount && splitLeft == null && index + op.SourceIndex < TotalCount);

            // Adjust base index of nodes that follow
            if (change != 0)
            {
                AdjustIndexesAfter(i, change);
            }

            // Handle child split/undersize
            if (splitLeft == null)
            {
                return(change);
            }
            else if (splitRight != null)
            {
                splitLeft = HandleChildSplit(i, splitLeft, ref splitRight, op.tob);
                return(change);
            }
            else
            {
                splitLeft = HandleUndersized(i, op.tob) ? this : null;
                return(change);
            }
        }
Example #5
0
 /// <summary>Performs an insert or replace operation in a <see cref="SparseAList{T}"/>.</summary>
 /// <param name="op">Describes the operation to be performed</param>
 /// <param name="index">Relative index in child node where the sparse
 /// operation began; <c>index + op.SourceIndex</c> is where the next
 /// insertion or replacement must occur. For example if the child
 /// node represents items 100-200, and op.SourceIndex is 7, and
 /// the absolute index of the start of the operation (op.AbsoluteIndex)
 /// is 98, then <c>index</c> will be -2 (98-100) and the next insertion
 /// or replacement will occur at index 5 in the child. <c>index</c> may
 /// be negative but <c>index + op.SourceIndex >= 0</c>.</param>
 /// <param name="splitLeft">If the node needs to split, splitLeft and
 /// splitRight are set to the new pieces. If the node is undersized,
 /// splitLeft is set to <c>this</c> (the called node) and splitRight
 /// is set to null.</param>
 /// <returns>Size change (always 0 for a replacement operation)</returns>
 /// <remarks>In a language with templates, I would change a couple
 /// of elements of <see cref="AListSparseOperation{T}"/> into
 /// template parameters.</remarks>
 internal virtual int DoSparseOperation(ref AListSparseOperation <T> op, int index, out AListNode <K, T> splitLeft, out AListNode <K, T> splitRight)
 {
     throw new NotSupportedException();
 }
Example #6
0
        private int DoInsert(ref AListSparseOperation <T> op, int index0, out AListNode <int, T> splitLeft, out AListNode <int, T> splitRight)
        {
            Debug.Assert(_totalCount + op.SourceCount >= _totalCount);             // caller ensures list size does not overflow

            if (op.WriteEmpty)
            {
                // SourceIndex will be 0 because inserting empty space always finishes on the first try.
                Debug.Assert(op.SourceIndex == 0);
                InsertSpace((uint)index0, op.SourceCount);
                op.SourceIndex = op.SourceCount;
                splitLeft      = splitRight = null;
                return(op.SourceCount);
            }

            int leftHere = _maxNodeSize - _list.Count;

            if (leftHere == 0)
            {
                SplitLeaf(out splitLeft, out splitRight);
                return(0);                // return without inserting anything
            }

            uint index = (uint)(index0 + op.SourceIndex);
            int  i;

            BinarySearch(index, out i);

            if (op.Source == null)
            {
                // Special case: insert a single item
                Debug.Assert(op.SourceCount == 1);
                _list.AutoRaiseCapacity(1, _maxNodeSize);

                _list.Insert(i, new Entry(index, op.Item));
                AdjustOffsetsStartingAt(i + 1, ref _list, 1);
                _totalCount++;
                op.SourceIndex++;
                splitLeft = splitRight = null;
                return(1);
            }

            splitLeft = splitRight = null;

            if (op.SparseSource != null)
            {
                var source   = op.SparseSource;
                var tempList = new InternalList <Entry>(leftHere);

                int?si;
                T   item;
                for (int prev = op.SourceIndex - 1; ; prev = si.Value)
                {
                    si   = prev;
                    item = source.NextHigherItem(ref si);
                    if (si == null)
                    {
                        break;
                    }
                    tempList.Add(new Entry {
                        Offset = (uint)(index0 + si.Value),
                        Item   = item
                    });
                    if (tempList.Count == leftHere)
                    {
                        break;
                    }
                }
                _list.InsertRangeHelper(i, tempList.Count);
                for (int j = 0; j < tempList.Count; j++)
                {
                    _list[i + j] = tempList[j];
                }

                int newSourceIndex       = si == null ? source.Count : si.Value + 1;
                int virtualItemsInserted = newSourceIndex - op.SourceIndex;
                op.SourceIndex = newSourceIndex;

                AdjustOffsetsStartingAt(i + tempList.Count, ref _list, virtualItemsInserted);
                _totalCount += (uint)virtualItemsInserted;
                return(virtualItemsInserted);
            }
            else
            {
                int c            = op.SourceCount;
                int leftToInsert = c - op.SourceIndex;
                Debug.Assert(leftToInsert > 0);
                int amtToIns = System.Math.Min(leftHere, leftToInsert);
                _list.AutoRaiseCapacity(amtToIns, _maxNodeSize);
                _list.InsertRangeHelper(i, amtToIns);
                for (int j = 0; j < amtToIns; j++)
                {
                    _list[i + j] = new Entry(index + (uint)j, op.Source[op.SourceIndex + j]);
                }
                AdjustOffsetsStartingAt(i + amtToIns, ref _list, amtToIns);
                _totalCount += (uint)amtToIns;

                op.SourceIndex += amtToIns;
                //if (tob != null) tob.AddingItems(slice, this, false);
                return(amtToIns);
            }
        }