RecyclableLongListCompatibilityList.ConvertAll & .CopyTo implemented. Tests added.
This commit is contained in:
1 parent
2012f51b6e
commit
89626511d6
2 files changed
+71
-7
No files matched your search
+33
@@ -231,6 +231,39 @@ namespace Recyclable.CollectionsTests
|
|||||||
_ = actual.Should().Equal(expectedData);
|
_ = actual.Should().Equal(expectedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||||
|
public void CopyToShouldCopyAllItemsInTheCorrectOrderWhenConstrainedRange(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in long[] itemIndexes)
|
||||||
|
{
|
||||||
|
// Prepare
|
||||||
|
var expectedData = testData.ToList();
|
||||||
|
foreach (var itemIndex in itemIndexes)
|
||||||
|
{
|
||||||
|
var rangedItemsCount = (int)Math.Max(itemIndex, 1);
|
||||||
|
TestCopyTo(0, rangedItemsCount);
|
||||||
|
|
||||||
|
rangedItemsCount = (int)(itemsCount - itemIndex);
|
||||||
|
TestCopyTo((int)itemIndex, rangedItemsCount);
|
||||||
|
|
||||||
|
rangedItemsCount = 1;
|
||||||
|
TestCopyTo((int)itemIndex, rangedItemsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCopyTo(int itemIndex, int rangedItemsCount)
|
||||||
|
{
|
||||||
|
using var list = new RecyclableLongList<long>(testData, minBlockSize, initialCapacity: itemsCount);
|
||||||
|
long[] expectedItems = new long[rangedItemsCount + itemIndex];
|
||||||
|
expectedData.CopyTo(itemIndex, expectedItems, itemIndex, rangedItemsCount);
|
||||||
|
long[] actualItems = new long[rangedItemsCount + itemIndex];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
list.CopyTo(itemIndex, actualItems, itemIndex, rangedItemsCount);
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
_ = actualItems.Should().Equal(expectedItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||||
public void CopyToShouldCopyAllItemsInTheCorrectOrderWhenFromStart(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize)
|
public void CopyToShouldCopyAllItemsInTheCorrectOrderWhenFromStart(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize)
|
||||||
|
|||||||
@@ -259,19 +259,50 @@ namespace Recyclable.Collections
|
|||||||
result._longCount = list._longCount;
|
result._longCount = list._longCount;
|
||||||
result._nextItemBlockIndex = list._nextItemBlockIndex;
|
result._nextItemBlockIndex = list._nextItemBlockIndex;
|
||||||
result._nextItemIndex = list._nextItemIndex;
|
result._nextItemIndex = list._nextItemIndex;
|
||||||
result._lastBlockWithData = lastBlockWithData;
|
result._lastBlockWithData = list._lastBlockWithData;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static void CopyTo<T>(this RecyclableLongList<T> list, T[] array)
|
public static void CopyTo<T>(this RecyclableLongList<T> list, T[] array) => DoCopyTo(list._memoryBlocks, 0, list._blockSize, list._longCount, array, 0);
|
||||||
//=> Array.Copy(list._memoryBlock, array, list._count);
|
|
||||||
=> throw new NotImplementedException();
|
private static void DoCopyTo<T>(T[][] sourceMemoryBlocks, long startingIndex, int blockSize, long itemsCount, Array destinationArray, int destinationArrayIndex)
|
||||||
|
{
|
||||||
|
if (itemsCount <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Replace with bit-shifting
|
||||||
|
int startingItemIndex = (int)(startingIndex % blockSize);
|
||||||
|
int memoryBlockIndex = (int)(startingIndex / blockSize);
|
||||||
|
int lastItemIndex;
|
||||||
|
|
||||||
|
ReadOnlySpan<T[]> sourceMemoryBlocksSpan = new(sourceMemoryBlocks);
|
||||||
|
// We're using lastItemIndex as temp storage for copied count, so that we can move the destination index. That's to avoid additional var.
|
||||||
|
Array.Copy(sourceMemoryBlocks[memoryBlockIndex], startingItemIndex, destinationArray, destinationArrayIndex, lastItemIndex = (int)Math.Min(itemsCount, blockSize - startingItemIndex));
|
||||||
|
memoryBlockIndex++;
|
||||||
|
destinationArrayIndex += lastItemIndex;
|
||||||
|
// TODO: Replace with bit-shifting
|
||||||
|
lastItemIndex = (int)((startingIndex + itemsCount) % blockSize);
|
||||||
|
int lastBlockIndex = (int)Math.Min((startingIndex + itemsCount) / blockSize, sourceMemoryBlocks.Length - 1);
|
||||||
|
|
||||||
|
while(memoryBlockIndex < lastBlockIndex)
|
||||||
|
{
|
||||||
|
Array.Copy(sourceMemoryBlocksSpan[memoryBlockIndex], 0, destinationArray, destinationArrayIndex, blockSize);
|
||||||
|
destinationArrayIndex += blockSize;
|
||||||
|
memoryBlockIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destinationArrayIndex < destinationArray.Length && memoryBlockIndex == lastBlockIndex)
|
||||||
|
{
|
||||||
|
Array.Copy(sourceMemoryBlocksSpan[lastBlockIndex], 0, destinationArray, destinationArrayIndex, lastItemIndex > 0 ? lastItemIndex : blockSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static void CopyTo<T>(this RecyclableLongList<T> list, int index, T[] array, int arrayIndex, int count)
|
//public static void CopyTo<T>(this RecyclableLongList<T> list, int index, T[] array, int arrayIndex, int count) => RecyclableLongList<T>.Helpers.CopyTo(list._memoryBlocks, index, list._blockSize, count, array, arrayIndex);
|
||||||
//=> Array.Copy(list._memoryBlock, index, array, arrayIndex, count);
|
public static void CopyTo<T>(this RecyclableLongList<T> list, int index, T[] array, int arrayIndex, int count) => DoCopyTo(list._memoryBlocks, index, list._blockSize, count, array, arrayIndex);
|
||||||
=> throw new NotImplementedException();
|
|
||||||
|
|
||||||
public static void ForEach<T>(this RecyclableLongList<T> list, Action<T> action)
|
public static void ForEach<T>(this RecyclableLongList<T> list, Action<T> action)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user