You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
6.7 KiB

using System;
using System.Collections.Generic;
using System.Text;
namespace Apewer
{
/// <summary>数组构建器。</summary>
public sealed class ArrayBuilder<T>
{
private T[] _array;
private int _capacity;
private int _count;
private int _step;
/// <summary>创建构建程序实例。</summary>
/// <param name="step">每次扩容的增量,最小值:1,默认值:256。</param>
/// <exception cref="ArgumentNullException"></exception>
public ArrayBuilder(int step = 256)
{
if (step < 1) throw new ArgumentOutOfRangeException(nameof(step));
_step = step;
_capacity = step;
_count = 0;
_array = new T[step];
}
private ArrayBuilder(ArrayBuilder<T> old)
{
_step = old._step;
_capacity = old._capacity;
_count = old._count;
_array = new T[_capacity];
if (_count > 0) Array.Copy(old._array, _array, _count);
}
/// <summary>获取或设置指定位置的元素,索引器范围为 [0, Length)。</summary>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public T this[int index]
{
get
{
if (index < 0 || index >= _count) throw new ArgumentOutOfRangeException("索引超出了当前数组的范围。");
return _array[index];
}
set
{
if (index < 0 || index >= _count) throw new ArgumentOutOfRangeException("索引超出了当前数组的范围。");
_array[index] = value;
}
}
/// <summary>缓冲区的容量。</summary>
public int Capacity { get => _capacity; }
/// <summary>当前的元素数量。</summary>
public int Length { get => _count; }
/// <summary>当前的元素数量。</summary>
public int Count { get => _count; }
/// <summary>指定元素在数组中的偏移位置。</summary>
public int IndexOf(T value)
{
var array = _array;
var length = _count;
if (length < 1) return -1;
for (var i = 0; i < length; i++)
{
var item = array[i];
if (item == null) continue;
if (item.Equals(value)) return i;
}
return -1;
}
/// <summary>已包含指定的元素。</summary>
public bool Contains(T value) => IndexOf(value) > -1;
/// <summary>添加元素。</summary>
public void Add(T item)
{
if (_capacity - _count < 1)
{
_capacity += _step;
var temp = new T[_capacity];
Array.Copy(_array, temp, _count);
_array = temp;
}
_array[_count] = item;
_count++;
}
/// <summary>添加多个元素。</summary>
public void Add(params T[] items)
{
if (items == null) return;
var length = items.Length;
if (length < 1) return;
if (_capacity - _count < length)
{
_capacity = _count + length;
var temp = new T[_capacity];
Array.Copy(_array, temp, _count);
_array = temp;
}
Array.Copy(items, _array, length);
_count += length;
}
/// <summary>添加多个元素。</summary>
public void Add(ICollection<T> items)
{
if (items == null) return;
var length = items.Count;
if (length < 1) return;
if (_capacity - _count < length)
{
_capacity = _count + length;
var temp = new T[_capacity];
Array.Copy(_array, temp, _count);
_array = temp;
}
items.CopyTo(_array, _count);
_count += length;
}
/// <summary>添加多个元素。</summary>
public void Add(IEnumerable<T> items)
{
if (items == null) return;
foreach (var item in items) Add(item);
}
/// <summary>添加元素。</summary>
/// <param name="buffer">要添加的元素数组。</param>
/// <param name="offset">buffer 的开始位置。</param>
/// <param name="count">buffer 的元素数量。</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public void Add(T[] buffer, int offset, int count)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
var length = buffer.Length;
if (offset < 0 || offset >= length || count < 0) throw new ArgumentOutOfRangeException();
if (offset + count > length) throw new ArgumentOutOfRangeException();
if (_capacity - _count < length)
{
_capacity = _count + length;
var temp = new T[_capacity];
Array.Copy(_array, temp, _count);
_array = temp;
}
Array.Copy(buffer, offset, _array, _count, count);
_count = _capacity;
}
/// <summary>清空所有元素。</summary>
public void Clear()
{
_capacity = 0;
_count = 0;
_array = new T[0];
}
// 修剪数组,去除剩余空间。
void Trim()
{
if (_count == 0)
{
if (_capacity > 0)
{
_capacity = 0;
_array = new T[0];
}
return;
}
if (_count == _capacity) return;
var array = new T[_count];
Array.Copy(_array, array, _count);
_capacity = _count;
}
/// <summary></summary>
/// <param name="clear"></param>
/// <returns></returns>
public T[] Export(bool clear = false)
{
if (_count == 0) return new T[0];
if (_count == _capacity) return _array;
var array = new T[_count];
Array.Copy(_array, array, _count);
return array;
}
/// <summary>克隆当前实例,生成新实例。</summary>
public ArrayBuilder<T> Clone() => new ArrayBuilder<T>(this);
/// <summary>使用 Export 方法实现从 ArrayBuilder&lt;T&gt; 到 T[] 的隐式转换。</summary>
public static implicit operator T[](ArrayBuilder<T> instance) => instance == null ? null : instance.Export();
}
}