RecyclableLongList.Insert implemented.
This commit is contained in:
1 parent
8714b5b977
commit
a80db94533
3 files changed
+80
-3
No files matched your search
@@ -90,6 +90,38 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
public static void MakeRoomAndSet(RecyclableLongList<T> list, long startingItemIndex, T item)
|
||||||
|
{
|
||||||
|
T[] currentBlock;
|
||||||
|
T[][] memoryBlocks = list._memoryBlocks;
|
||||||
|
int blockSizeMinus1 = list._blockSizeMinus1,
|
||||||
|
targetItemIndex = (int)(startingItemIndex & blockSizeMinus1),
|
||||||
|
targetBlockIndex = (int)(startingItemIndex >> list._blockSizePow2BitShift) + (targetItemIndex != 0 ? 1 : 0),
|
||||||
|
lastTakenBlockIndex = list._lastBlockWithData;
|
||||||
|
|
||||||
|
if (list._nextItemIndex == 0)
|
||||||
|
{
|
||||||
|
new Span<T>(memoryBlocks[lastTakenBlockIndex + 1])[0] = memoryBlocks[lastTakenBlockIndex][blockSizeMinus1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int currentBlockIndex = lastTakenBlockIndex;
|
||||||
|
while (currentBlockIndex > targetBlockIndex)
|
||||||
|
{
|
||||||
|
new Span<T>(currentBlock = memoryBlocks[currentBlockIndex--], 0, blockSizeMinus1)
|
||||||
|
.CopyTo(new Span<T>(currentBlock, 1, blockSizeMinus1));
|
||||||
|
new Span<T>(currentBlock)[0] = memoryBlocks[currentBlockIndex][blockSizeMinus1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastTakenBlockIndex >= 0)
|
||||||
|
{
|
||||||
|
new Span<T>(currentBlock = memoryBlocks[targetBlockIndex], targetItemIndex, blockSizeMinus1 - targetItemIndex)
|
||||||
|
.CopyTo(new Span<T>(currentBlock, targetItemIndex + 1, blockSizeMinus1 - targetItemIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
new Span<T>(memoryBlocks[targetBlockIndex])[targetItemIndex] = item;
|
||||||
|
}
|
||||||
|
|
||||||
public static void CopyTo(T[][] sourceMemoryBlocks, long startingIndex, int blockSize, long itemsCount, T[] destinationArray, int destinationArrayIndex)
|
public static void CopyTo(T[][] sourceMemoryBlocks, long startingIndex, int blockSize, long itemsCount, T[] destinationArray, int destinationArrayIndex)
|
||||||
{
|
{
|
||||||
if (itemsCount <= 0)
|
if (itemsCount <= 0)
|
||||||
|
|||||||
@@ -835,7 +835,43 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Insert(int index, T item) => throw new NotSupportedException();
|
public void Insert(int index, T item)
|
||||||
|
{
|
||||||
|
if (index > _longCount++ || index < 0)
|
||||||
|
{
|
||||||
|
_longCount--;
|
||||||
|
Helpers.ThrowIndexOutOfRangeException($"Argument \"{nameof(index)}\" = {index} is out of range. Expected value between 0 and {_longCount}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_capacity < _longCount)
|
||||||
|
{
|
||||||
|
_capacity = Helpers.Resize(this, _blockSize, _blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)_longCount)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_longCount > 1)
|
||||||
|
{
|
||||||
|
Helpers.MakeRoomAndSet(this, index, item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new Span<T>(_memoryBlocks[0])[0] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_nextItemIndex < _blockSizeMinus1)
|
||||||
|
{
|
||||||
|
if (++_nextItemIndex == 1)
|
||||||
|
{
|
||||||
|
_lastBlockWithData++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_nextItemIndex = 0;
|
||||||
|
_nextItemBlockIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_version++;
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public long LongIndexOf(T item)
|
public long LongIndexOf(T item)
|
||||||
|
|||||||
@@ -513,10 +513,19 @@ namespace Recyclable.CollectionsTests
|
|||||||
public void InsertAtTheBeginningShouldMoveItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
public void InsertAtTheBeginningShouldMoveItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||||
{
|
{
|
||||||
// Prepare
|
// Prepare
|
||||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize);
|
using var list = new RecyclableLongList<long>();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
_ = Assert.Throws<NotSupportedException>(() => list.Insert(0, -1));
|
foreach (var item in testData)
|
||||||
|
{
|
||||||
|
list.Insert(0, item);
|
||||||
|
_ = list.Count.Should().Be((int)item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||||
|
_ = list.Count.Should().Be((int)itemsCount);
|
||||||
|
_ = list.Should().ContainInConsecutiveOrder(testData.Reverse());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|||||||
Reference in new issue
Block a user