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:
1 parent
e312accfe5
commit
e6224ebe44
3 files changed
+209
-123
No files matched your search
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user