RecyclableList.BlockCount renamed => RecyclableList.ReservedBlockCount. Fixed to always include the last block.
RecyclableList.LastTakenBlockIndex property added for some scenarios. RecyclableList.IndexOf & .LongIndexOf fixed to use the correct index. RecyclableArrayList.AddRange(RecyclableList<T> items) fixed to use the correct index. Some test cases excluded, where needed.
This commit is contained in:
1 parent
0a402e2d13
commit
b91c4476eb
4 files changed
+27
-12
No files matched your search
@@ -279,7 +279,7 @@ namespace Recyclable.Collections
|
|||||||
itemsSpan = new(items.MemoryBlocks[blockIndex], 0, (int)sourceItemsCount);
|
itemsSpan = new(items.MemoryBlocks[blockIndex], 0, (int)sourceItemsCount);
|
||||||
itemsSpan.CopyTo(targetSpan);
|
itemsSpan.CopyTo(targetSpan);
|
||||||
}
|
}
|
||||||
else if (blockIndex < items.BlockCount)
|
else if (blockIndex <= items.LastTakenBlockIndex)
|
||||||
{
|
{
|
||||||
itemsSpan = new(items.MemoryBlocks[blockIndex], 0, items.NextItemIndex);
|
itemsSpan = new(items.MemoryBlocks[blockIndex], 0, items.NextItemIndex);
|
||||||
itemsSpan.CopyTo(targetSpan);
|
itemsSpan.CopyTo(targetSpan);
|
||||||
|
|||||||
@@ -31,16 +31,16 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
public int Count => checked((int)_longCount);
|
public int Count => checked((int)_longCount);
|
||||||
public bool IsReadOnly { get; }
|
public bool IsReadOnly { get; }
|
||||||
|
public int LastTakenBlockIndex => _lastBlockIndex - (_nextItemIndex > 0 ? 0 : 1);
|
||||||
|
|
||||||
protected long _longCount;
|
protected long _longCount;
|
||||||
|
|
||||||
public long LongCount
|
public long LongCount
|
||||||
{
|
{
|
||||||
get => _longCount;
|
get => _longCount;
|
||||||
set => _longCount = value;
|
set => _longCount = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int BlockCount => (int)(_capacity / _blockSize);
|
public int ReservedBlockCount => (int)(_capacity / _blockSize) + (_capacity % _blockSize > 0 ? 1 : 0);
|
||||||
public int BlockSize => _blockSize;
|
public int BlockSize => _blockSize;
|
||||||
public int LastBlockIndex => _lastBlockIndex;
|
public int LastBlockIndex => _lastBlockIndex;
|
||||||
public int NextItemIndex => _nextItemIndex;
|
public int NextItemIndex => _nextItemIndex;
|
||||||
@@ -70,7 +70,7 @@ namespace Recyclable.Collections
|
|||||||
T[][] memoryBlocks = list._memoryBlocks;
|
T[][] memoryBlocks = list._memoryBlocks;
|
||||||
if (blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
if (blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
blockArrayPool.Return(memoryBlocks[list.BlockCount - 1]);
|
blockArrayPool.Return(memoryBlocks[list.ReservedBlockCount - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
list._capacity -= blockSize;
|
list._capacity -= blockSize;
|
||||||
@@ -97,7 +97,7 @@ namespace Recyclable.Collections
|
|||||||
long capacity = _capacity;
|
long capacity = _capacity;
|
||||||
long available = capacity - copied;
|
long available = capacity - copied;
|
||||||
|
|
||||||
Span<T[]> memoryBlocksSpan = new(_memoryBlocks, 0, BlockCount);
|
Span<T[]> memoryBlocksSpan = new(_memoryBlocks, 0, ReservedBlockCount);
|
||||||
Span<T> blockArraySpan;
|
Span<T> blockArraySpan;
|
||||||
var memoryBlocksCount = memoryBlocksSpan.Length;
|
var memoryBlocksCount = memoryBlocksSpan.Length;
|
||||||
while (true)
|
while (true)
|
||||||
@@ -171,7 +171,7 @@ namespace Recyclable.Collections
|
|||||||
blockSize = _blockSize;
|
blockSize = _blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
var memoryBlocksCount = BlockCount;
|
var memoryBlocksCount = ReservedBlockCount;
|
||||||
memoryBlocksSpan = new(_memoryBlocks, 0, memoryBlocksCount);
|
memoryBlocksSpan = new(_memoryBlocks, 0, memoryBlocksCount);
|
||||||
blockArraySpan = new Span<T>(memoryBlocksSpan[targetBlockIdx], 0, blockSize);
|
blockArraySpan = new Span<T>(memoryBlocksSpan[targetBlockIdx], 0, blockSize);
|
||||||
foreach (var item in source)
|
foreach (var item in source)
|
||||||
@@ -698,7 +698,7 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
if (_blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
if (_blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
Span<T[]> memoryBlocksSpan = new(_memoryBlocks, 0, BlockCount);
|
Span<T[]> memoryBlocksSpan = new(_memoryBlocks, 0, ReservedBlockCount);
|
||||||
int memoryBlocksCount = memoryBlocksSpan.Length;
|
int memoryBlocksCount = memoryBlocksSpan.Length;
|
||||||
ArrayPool<T> blockArrayPool = _blockArrayPool;
|
ArrayPool<T> blockArrayPool = _blockArrayPool;
|
||||||
for (int toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++)
|
for (int toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++)
|
||||||
@@ -748,14 +748,14 @@ namespace Recyclable.Collections
|
|||||||
? ItemNotFoundIndex
|
? ItemNotFoundIndex
|
||||||
: _lastBlockIndex == 0 || (_lastBlockIndex == 1 && _nextItemIndex == 0)
|
: _lastBlockIndex == 0 || (_lastBlockIndex == 1 && _nextItemIndex == 0)
|
||||||
? Array.IndexOf(_memoryBlocks[0], item, 0, (int)_longCount)
|
? Array.IndexOf(_memoryBlocks[0], item, 0, (int)_longCount)
|
||||||
: (int)DoIndexOf(item, _memoryBlocks, BlockCount - 1, _blockSize, _nextItemIndex);
|
: (int)DoIndexOf(item, _memoryBlocks, LastTakenBlockIndex, _blockSize, _nextItemIndex);
|
||||||
|
|
||||||
public void Insert(int index, T item) => throw new NotSupportedException();
|
public void Insert(int index, T item) => throw new NotSupportedException();
|
||||||
public long LongIndexOf(T item) => _longCount == 0
|
public long LongIndexOf(T item) => _longCount == 0
|
||||||
? ItemNotFoundIndex
|
? ItemNotFoundIndex
|
||||||
: _lastBlockIndex == 0 || (_lastBlockIndex == 1 && _nextItemIndex == 0)
|
: _lastBlockIndex == 0 || (_lastBlockIndex == 1 && _nextItemIndex == 0)
|
||||||
? Array.IndexOf(_memoryBlocks[0], item, 0, (int)_longCount)
|
? Array.IndexOf(_memoryBlocks[0], item, 0, (int)_longCount)
|
||||||
: DoIndexOf(item, _memoryBlocks, BlockCount - 1, _blockSize, _nextItemIndex);
|
: DoIndexOf(item, _memoryBlocks, LastTakenBlockIndex, _blockSize, _nextItemIndex);
|
||||||
|
|
||||||
public bool Remove(T item)
|
public bool Remove(T item)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ namespace Recyclable.Collections
|
|||||||
LongCount--;
|
LongCount--;
|
||||||
if ((List.Capacity * _blockSize) - LongCount == _blockSize)
|
if ((List.Capacity * _blockSize) - LongCount == _blockSize)
|
||||||
{
|
{
|
||||||
List.RemoveBlock(List.BlockCount - 1);
|
List.RemoveBlock(List.ReservedBlockCount - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return toRemove;
|
return toRemove;
|
||||||
|
|||||||
@@ -291,8 +291,13 @@ namespace Recyclable.CollectionsTests
|
|||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))]
|
[MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))]
|
||||||
public void RemoveShouldRaiseNotSupportedException(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
public void RemoveShouldRaiseNotSupportedExceptionWhenNotLastItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||||
{
|
{
|
||||||
|
if (itemsCount is 0 or 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
using var list = new RecyclableList<long>(testData, minBlockSize: targetBlockSize);
|
using var list = new RecyclableList<long>(testData, minBlockSize: targetBlockSize);
|
||||||
|
|
||||||
@@ -302,8 +307,13 @@ namespace Recyclable.CollectionsTests
|
|||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))]
|
[MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))]
|
||||||
public void RemoveAtShouldRaiseNotSupportedException(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
public void RemoveAtShouldRaiseNotSupportedExceptionWhenNotLastItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||||
{
|
{
|
||||||
|
if (itemsCount is 0 or 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
using var list = new RecyclableList<long>(testData, minBlockSize: targetBlockSize);
|
using var list = new RecyclableList<long>(testData, minBlockSize: targetBlockSize);
|
||||||
|
|
||||||
@@ -530,6 +540,11 @@ namespace Recyclable.CollectionsTests
|
|||||||
[MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))]
|
[MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))]
|
||||||
public void LongIndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
public void LongIndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||||
{
|
{
|
||||||
|
if (itemsCount == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
using var list = new RecyclableList<long>(testData, minBlockSize: targetBlockSize);
|
using var list = new RecyclableList<long>(testData, minBlockSize: targetBlockSize);
|
||||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||||
|
|||||||
Reference in new issue
Block a user