diff --git a/Recyclable.Collections/RecyclableList.cs b/Recyclable.Collections/RecyclableList.cs index de708f3..434615f 100644 --- a/Recyclable.Collections/RecyclableList.cs +++ b/Recyclable.Collections/RecyclableList.cs @@ -505,7 +505,7 @@ namespace Recyclable.Collections public bool Contains(T item) => _memoryBlocks.Any(x => x.Contains(item)); - public void CopyTo(T[] array, int arrayIndex) => _memoryBlocks.CopyTo(0, _blockSize, (int)(LongCount % _blockSize), array, arrayIndex); + public void CopyTo(T[] array, int arrayIndex) => _memoryBlocks.CopyTo(0, _blockSize, _longCount, array, arrayIndex); public IEnumerator GetEnumerator() => _memoryBlocks.Enumerate(_blockSize, LongCount).GetEnumerator(); diff --git a/Recyclable.Collections/RecyclableListExtensions.cs b/Recyclable.Collections/RecyclableListExtensions.cs index 2799c22..e873729 100644 --- a/Recyclable.Collections/RecyclableListExtensions.cs +++ b/Recyclable.Collections/RecyclableListExtensions.cs @@ -15,41 +15,26 @@ namespace Recyclable.Collections } } - public static void CopyTo(this T[][] arrays, long startingIndex, int blockSize, int lastBlockSize, T[] destinationArray, int destinationArrayIndex) + public static void CopyTo(this T[][] sourceMemoryBlocks, long startingIndex, int blockSize, long itemsCount, T[] destinationArray, int destinationArrayIndex) { - Span arrayMemory = destinationArray.AsSpan(); - arrayMemory = arrayMemory[destinationArrayIndex..]; - int startingArrayIndex = (int)(startingIndex / blockSize); - startingIndex %= blockSize; - if (arrays.LongLength > 0) + Memory sourceBlockMemory; + Memory destinationArrayMemory; + int startingBlockIndex = (int)(startingIndex / blockSize); + int lastBlockIndex = (int)((itemsCount / blockSize) + (itemsCount - (itemsCount / blockSize) > 0 ? 1 : 0)) - 1; + Span sourceMemoryBlocksSpan = new(sourceMemoryBlocks, startingBlockIndex, lastBlockIndex - startingBlockIndex + 1); + destinationArrayMemory = new Memory(destinationArray, destinationArrayIndex, destinationArray.Length); + int memoryBlockIndex; + for (memoryBlockIndex = 0; memoryBlockIndex < lastBlockIndex; memoryBlockIndex++) { - ReadOnlySpan sourceMemory = arrays[0].AsSpan(); - var maxToCopy = (int)Math.Min(blockSize - startingIndex, arrayMemory.Length); - if (arrays.LongLength == 1) - { - maxToCopy = (int)Math.Min(maxToCopy, lastBlockSize); - } - - sourceMemory = sourceMemory[(int)startingIndex..maxToCopy]; - sourceMemory.CopyTo(arrayMemory); - arrayMemory = arrayMemory[maxToCopy..]; + sourceBlockMemory = new(sourceMemoryBlocksSpan[memoryBlockIndex], 0, blockSize); + sourceBlockMemory.CopyTo(destinationArrayMemory); + destinationArrayMemory = destinationArrayMemory[blockSize..]; } - for (var arrayIdx = startingArrayIndex + 1; arrayIdx < arrays.Length - 1 && arrayMemory.Length > 0; arrayIdx++) + if (itemsCount % blockSize > 0) { - ReadOnlySpan sourceMemory = arrays[arrayIdx].AsSpan(); - var maxToCopy = Math.Min(blockSize, arrayMemory.Length); - sourceMemory = sourceMemory[..maxToCopy]; - sourceMemory.CopyTo(arrayMemory); - arrayMemory = arrayMemory[maxToCopy..]; - } - - if (arrays.Length > 1 && arrayMemory.Length > 0) - { - ReadOnlySpan sourceMemory = arrays[^1].AsSpan(); - var maxToCopy = Math.Min(lastBlockSize, arrayMemory.Length); - sourceMemory = sourceMemory[..maxToCopy]; - sourceMemory.CopyTo(arrayMemory); + sourceBlockMemory = new(sourceMemoryBlocksSpan[^1], 0, (int)(itemsCount % blockSize)); + sourceBlockMemory.CopyTo(destinationArrayMemory); } }