RecyclableList.AddRange(IEnumerable<T> source) fixed to properly add items when we can get non-enumerated count.

This commit is contained in:
Marek Lemańczyk committed 2023-03-11 23:15:04 +01:00
1 parent 1ea0af8d34
commit 91fae49bdb
1 file changed
+10 -12
+10 -12
View File
@@ -525,42 +525,40 @@ namespace Recyclable.Collections
long capacity = _capacity; long capacity = _capacity;
long oldLongCount = _longCount; long oldLongCount = _longCount;
int blockSize = _blockSize; int blockSize = _blockSize;
int targetItemIdx = (int)(oldLongCount % blockSize); int targetItemIdx = _nextItemIndex;
int targetBlockIdx = (targetItemIdx / blockSize) + (targetItemIdx > 0 ? 1 : 0); int targetBlockIdx = _lastBlockIndex;
Span<T[]> memoryBlocksSpan; Span<T[]> memoryBlocksSpan;
Span<T> blockArraySpan; Span<T> blockArraySpan;
if (source.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity)) if (source.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity))
{ {
int requiredCapacity = targetItemIdx + requiredAdditionalCapacity; long requiredCapacity = oldLongCount + requiredAdditionalCapacity;
if (capacity < requiredCapacity) if (capacity < requiredCapacity)
{ {
_ = EnsureCapacity(requiredCapacity); _ = EnsureCapacity(requiredCapacity);
blockSize = _blockSize; blockSize = _blockSize;
targetBlockIdx = (targetItemIdx / blockSize) + (targetItemIdx > 0 ? 1 : 0);
targetItemIdx = (int)(oldLongCount % blockSize);
} }
memoryBlocksSpan = new(_memoryBlocks); var memoryBlocksCount = _memoryBlocks.Length;
var memoryBlocksCount = memoryBlocksSpan.Length; memoryBlocksSpan = new(_memoryBlocks, 0, memoryBlocksCount);
blockArraySpan = new Span<T>(memoryBlocksSpan[targetBlockIdx]); blockArraySpan = new Span<T>(memoryBlocksSpan[targetBlockIdx], 0, blockSize);
foreach (var item in source) foreach (var item in source)
{ {
blockArraySpan[targetItemIdx++] = item; blockArraySpan[targetItemIdx++] = item;
if (targetItemIdx == blockSize) if (targetItemIdx == blockSize)
{ {
targetBlockIdx++; targetBlockIdx++;
targetItemIdx = 0;
if (targetBlockIdx == memoryBlocksCount) if (targetBlockIdx == memoryBlocksCount)
{ {
break; break;
} }
targetItemIdx = 0; blockArraySpan = new Span<T>(memoryBlocksSpan[targetBlockIdx], 0, blockSize);
blockArraySpan = new Span<T>(memoryBlocksSpan[targetBlockIdx]);
} }
} }
_longCount = (targetBlockIdx * blockSize) + targetItemIdx; _longCount = requiredCapacity;
_lastBlockIndex = targetBlockIdx; _lastBlockIndex = targetBlockIdx;
_nextItemIndex = targetItemIdx; _nextItemIndex = targetItemIdx;
return; return;