Fixed handling of empty lists in RecyclableArrayList.

Some RecyclableList properties made public to allow use in RecyclableArrayList.

Added support for RecyclableList in RecyclableArrayList.AddRange.

Additional tests added for RecyclableArrayList.
This commit is contained in:
Marek Lemańczyk committed 2023-03-19 20:37:18 +01:00
1 parent e312accfe5
commit e6224ebe44
3 files changed
+209 -123

No files matched your search

+75 -3
View File
@@ -11,9 +11,9 @@ namespace Recyclable.Collections
protected T[] _memoryBlock;
private static void ThrowArgumentOutOfRangeException()
private static void ThrowArgumentOutOfRangeException(in string message)
{
throw new ArgumentOutOfRangeException("index");
throw new ArgumentOutOfRangeException(message, (Exception?)null);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -162,6 +162,11 @@ namespace Recyclable.Collections
public void AddRange(in T[] items)
{
if (items.LongLength == 0)
{
return;
}
int sourceItemsCount = items.Length;
int targetCapacity = _count + sourceItemsCount;
if (_capacity < targetCapacity)
@@ -177,6 +182,11 @@ namespace Recyclable.Collections
public void AddRange(List<T> items)
{
if (items.Count == 0)
{
return;
}
var sourceItemsCount = items.Count;
var targetCapacity = _count + sourceItemsCount;
if (_capacity < targetCapacity)
@@ -190,6 +200,11 @@ namespace Recyclable.Collections
public void AddRange(IList<T> items)
{
if (items.Count == 0)
{
return;
}
var sourceItemsCount = items.Count;
var targetCapacity = _count + sourceItemsCount;
if (_capacity < targetCapacity)
@@ -203,6 +218,11 @@ namespace Recyclable.Collections
public void AddRange(RecyclableArrayList<T> items)
{
if (items.Count == 0)
{
return;
}
var sourceItemsCount = items._count;
var targetCapacity = _count + sourceItemsCount;
if (_capacity < targetCapacity)
@@ -216,6 +236,58 @@ namespace Recyclable.Collections
_count = targetCapacity;
}
public void AddRange(RecyclableList<T> items)
{
if (items.LongCount == 0)
{
return;
}
var sourceItemsCount = items.LongCount;
if (sourceItemsCount > int.MaxValue)
{
ThrowArgumentOutOfRangeException($"The number of items exceeds the maximum capacity of {nameof(RecyclableArrayList<T>)}, equal {int.MaxValue}, equal {int.MaxValue}. Please consider using {nameof(RecyclableList<T>)}, instead");
}
if (_count + sourceItemsCount > int.MaxValue)
{
ThrowArgumentOutOfRangeException($"The total number of items in source and target table exceeds the maximum capacity of {nameof(RecyclableArrayList<T>)}, equal {int.MaxValue}. Please consider using {nameof(RecyclableList<T>)}, instead");
}
int targetCapacity = _count + (int)sourceItemsCount;
if (_capacity < targetCapacity)
{
_ = EnsureCapacity(targetCapacity);
}
Span<T> targetSpan = new Span<T>(_memoryBlock)[_count..],
itemsSpan;
int blockIndex,
sourceBlockSize = items.BlockSize,
lastBlockIndex = (int)(sourceItemsCount / sourceBlockSize) - 1;
for (blockIndex = 0; blockIndex <= lastBlockIndex; blockIndex++)
{
itemsSpan = new(items.MemoryBlocks[blockIndex], 0, sourceBlockSize);
itemsSpan.CopyTo(targetSpan);
targetSpan = targetSpan[sourceBlockSize..];
}
if (blockIndex == 0)
{
itemsSpan = new(items.MemoryBlocks[blockIndex], 0, (int)sourceItemsCount);
itemsSpan.CopyTo(targetSpan);
}
else if (blockIndex < items.BlockCount)
{
itemsSpan = new(items.MemoryBlocks[blockIndex], 0, items.NextItemIndex);
itemsSpan.CopyTo(targetSpan);
}
_count = targetCapacity;
}
public void AddRange(IEnumerable<T> source, int growByCount = RecyclableDefaults.MinPooledArrayLength)
{
if (source is T[] sourceArray)
@@ -375,7 +447,7 @@ namespace Recyclable.Collections
if (index >= oldCount)
{
ThrowArgumentOutOfRangeException();
ThrowArgumentOutOfRangeException($"Argument \"{index}\" is out of range. The current version supports removing the last element, only ");
return;
}
+7 -3
View File
@@ -22,6 +22,9 @@ namespace Recyclable.Collections
protected ArrayPool<T> _blockArrayPool;
protected T[][] _memoryBlocks;
public int BlockSize => _blockSize;
public int BlockCount => _memoryBlocks.Length;
private long _capacity;
public long Capacity
{
@@ -29,7 +32,8 @@ namespace Recyclable.Collections
protected set => _capacity = value;
}
public int Count => (int)_longCount;
public int Count => checked((int)_longCount);
public bool IsReadOnly { get; }
protected long _longCount;
@@ -39,8 +43,8 @@ namespace Recyclable.Collections
set => _longCount = value;
}
public bool IsReadOnly { get; }
public int BlockCount => _memoryBlocks.Length;
public int LastBlockIndex => _lastBlockIndex;
public int NextItemIndex => _nextItemIndex;
private static void RemoveAt(RecyclableList<T> list, long index, ArrayPool<T> blockArrayPool)
{