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; }
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(); } }
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(); } }
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; }