public void Merge(ref LinkedListStruct sourceList)
            {
                if (ReferenceEquals(HeadNode.Next, TailNode))
                {
                    sourceList.HeadNode.Size += HeadNode.Size;

                    var head = HeadNode;
                    var tail = TailNode;

                    HeadNode = sourceList.HeadNode;
                    TailNode = sourceList.TailNode;

                    sourceList.HeadNode = head;
                    sourceList.TailNode = tail;
                }
                else if (ReferenceEquals(sourceList.HeadNode.Next, sourceList.TailNode))
                {
                    TailNode.Size += sourceList.HeadNode.Size;
                }
                else
                {
                    if (TailNode.Size > 0 || sourceList.HeadNode.Size > 0)
                    {
                        TailNode.Size += sourceList.HeadNode.Size;
                        TailNode.Next  = sourceList.HeadNode.Next;
                        sourceList.HeadNode.Next.Prev = TailNode;
                        TailNode = sourceList.TailNode;

                        sourceList.TailNode      = ListManager.GetGapNode();
                        sourceList.HeadNode.Next = sourceList.TailNode;
                        sourceList.TailNode.Prev = sourceList.HeadNode;
                    }
                    else
                    {
                        var realizedSource = (RealizedNode)TailNode.Prev;
                        var realizedTarget = (RealizedNode)sourceList.HeadNode.Next;
                        var tailNode       = TailNode;

                        realizedSource.Next = realizedTarget;
                        realizedTarget.Prev = realizedSource;
                        TailNode            = sourceList.TailNode;

                        sourceList.TailNode      = tailNode;
                        sourceList.HeadNode.Next = sourceList.TailNode;
                        sourceList.TailNode.Prev = sourceList.HeadNode;
                    }
                }

                LongCount += sourceList.LongCount;

                sourceList.LongCount     = 0;
                sourceList.HeadNode.Size = 0;
                sourceList.TailNode.Size = 0;
            }
Esempio n. 2
0
        private protected void SwapImpl(SparseLinkedListBase <T> targetList)
        {
            try
            {
                EnterStructureChange();
                targetList.EnterStructureChange();

                var left  = new LinkedListStruct(this);
                var right = new LinkedListStruct(targetList);

                left.Store(targetList);
                right.Store(this);
            }
            finally
            {
                LeaveStructureChange();
                targetList.LeaveStructureChange();
            }
        }
Esempio n. 3
0
        private protected void MergeImpl(SparseLinkedListBase <T> sourceList)
        {
            if (ReferenceEquals(this, sourceList))
            {
                throw new InvalidOperationException("Cannot split into self");
            }

            if (ReferenceEquals(Manager, sourceList.Manager) == false)
            {
                throw new InvalidOperationException("Manager of source list and target list must be the same");
            }

            if (sourceList.LongCount == 0)
            {
                return;
            }

            try
            {
                EnterStructureChange();
                sourceList.EnterStructureChange();

                var first  = new LinkedListStruct(this);
                var second = new LinkedListStruct(sourceList);

                first.Merge(ref second);

                first.Store(this);
                second.Store(sourceList);
            }
            finally
            {
                LeaveStructureChange();
                sourceList.LeaveStructureChange();
            }
        }
Esempio n. 4
0
        private protected void SplitAtImpl(long index, SparseLinkedListBase <T> targetList)
        {
            if (ReferenceEquals(this, targetList))
            {
                throw new InvalidOperationException("Cannot split into self");
            }

            if (ReferenceEquals(Manager, targetList.Manager) == false)
            {
                throw new InvalidOperationException("Manager of source list and target list must be the same");
            }

            if (index == LongCount)
            {
                return;
            }

            try
            {
                EnterStructureChange();
                targetList.EnterStructureChange();

                if (index == 0)
                {
                    if (targetList.LongCount == 0)
                    {
                        SwapImpl(targetList);
                    }
                    else
                    {
                        var left  = new LinkedListStruct(this);
                        var right = new LinkedListStruct(targetList);

                        left.Merge(ref right);

                        left.Store(targetList);
                        right.Store(this);
                    }

                    return;
                }

                var cursor = NavigateTo(index);

                if (targetList.Count == 0)
                {
                    var left  = new LinkedListStruct(this);
                    var right = new LinkedListStruct(targetList);

                    left.Split(ref cursor, ref right);

                    left.Store(this);
                    right.Store(targetList);
                }
                else
                {
                    var left  = new LinkedListStruct(this);
                    var mid   = new LinkedListStruct(Manager);
                    var right = new LinkedListStruct(targetList);

                    left.Split(ref cursor, ref mid);
                    mid.Merge(ref right);

                    left.Store(this);
                    mid.Store(targetList);

                    right.Release();
                }
            }
            finally
            {
                LeaveStructureChange();
                targetList.LeaveStructureChange();
            }
        }
            public void Split(ref NodeCursor cursor, ref LinkedListStruct targetList)
            {
                var index          = cursor.Index;
                var nodeSplitIndex = (int)(index - cursor.NodeOffset);
                var nodeSplitCount = (int)(cursor.Node.Size - nodeSplitIndex);
                var targetListTail = targetList.TailNode;

                if (cursor.Node is GapNode gapNode)
                {
                    if (ReferenceEquals(HeadNode, gapNode))
                    {
                        // Target
                        targetList.HeadNode.Size = nodeSplitCount;
                        targetList.HeadNode.Next = gapNode.Next;
                        gapNode.Next.Prev        = targetList.HeadNode;
                        targetList.TailNode      = TailNode;

                        // Source
                        TailNode      = targetListTail;
                        TailNode.Prev = HeadNode;
                        HeadNode.Next = TailNode;

                        HeadNode.Size = index;
                        TailNode.Size = 0;
                    }
                    else if (ReferenceEquals(TailNode, gapNode))
                    {
                        TailNode.Size            -= nodeSplitCount;
                        targetList.HeadNode.Size += nodeSplitCount;
                    }
                    else
                    {
                        var prevNode = gapNode.Prev;

                        // Target
                        targetList.HeadNode.Size = nodeSplitCount;
                        targetList.HeadNode.Next = gapNode.Next;
                        gapNode.Next.Prev        = targetList.HeadNode;
                        targetList.TailNode      = TailNode;

                        // Source
                        TailNode      = targetListTail;
                        TailNode.Prev = prevNode;

                        prevNode.Next = TailNode;
                        TailNode.Size = nodeSplitIndex;

                        ListManager.ReleaseNode(gapNode);
                    }
                }
                else if (nodeSplitIndex == 0)
                {
                    var node = cursor.Node;
                    var prev = node.Prev;

                    // Target
                    targetList.HeadNode.Next = node;
                    node.Prev           = targetList.HeadNode;
                    targetList.TailNode = TailNode;

                    if (prev is GapNode prevGapNode)
                    {
                        if (ReferenceEquals(HeadNode, prev))
                        {
                            TailNode      = targetListTail;
                            TailNode.Prev = HeadNode;
                            HeadNode.Next = TailNode;
                        }
                        else
                        {
                            TailNode      = prevGapNode;
                            TailNode.Next = null;

                            ListManager.ReleaseNode(targetListTail);
                        }
                    }
                    else
                    {
                        TailNode      = targetListTail;
                        prev.Next     = TailNode;
                        TailNode.Prev = prev;
                    }
                }
                else
                {
                    var sourceRealizedNode = (RealizedNode)cursor.Node;
                    var targetRealizedNode = ListManager.GetRealizedNode();

                    var sourceSpan = sourceRealizedNode.Span.Slice(nodeSplitIndex, nodeSplitCount);
                    var targetSpan = targetRealizedNode.Span.Slice(0, nodeSplitCount);

                    sourceSpan.CopyTo(targetSpan);

                    // Target
                    targetRealizedNode.Size      = nodeSplitCount;
                    targetList.HeadNode.Next     = targetRealizedNode;
                    targetRealizedNode.Prev      = targetList.HeadNode;
                    targetRealizedNode.Next      = sourceRealizedNode.Next;
                    sourceRealizedNode.Next.Prev = targetRealizedNode;
                    targetList.TailNode          = TailNode;

                    // Source
                    sourceRealizedNode.Size = nodeSplitIndex;
                    TailNode                = targetListTail;
                    TailNode.Prev           = sourceRealizedNode;
                    sourceRealizedNode.Next = TailNode;
                }

                targetList.LongCount = LongCount - index;

                LongCount = index;
            }