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.
320 lines
7.7 KiB
320 lines
7.7 KiB
4 years ago
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
namespace AX.AudioSystem
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// 构造一个暴露内部数组的 List。
|
||
|
/// </summary>
|
||
|
internal class BetterList<T>
|
||
|
{
|
||
|
private const int DefaultCapacity = 4;
|
||
|
private const int MaxArrayLength = 0x7fefffff;
|
||
|
|
||
|
private static readonly T[] emptyArray = new T[0];
|
||
|
|
||
|
private T[] items;
|
||
|
private int size;
|
||
|
|
||
|
public BetterList()
|
||
|
{
|
||
|
items = emptyArray;
|
||
|
}
|
||
|
|
||
|
public BetterList(int capacity)
|
||
|
{
|
||
|
if (capacity < 0)
|
||
|
throw new ArgumentOutOfRangeException("capacity");
|
||
|
|
||
|
if (capacity == 0)
|
||
|
items = emptyArray;
|
||
|
else
|
||
|
items = new T[capacity];
|
||
|
}
|
||
|
|
||
|
public int Capacity
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return items.Length;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
if (value < size)
|
||
|
throw new ArgumentOutOfRangeException("capacity");
|
||
|
|
||
|
if (value != items.Length)
|
||
|
{
|
||
|
if (value > 0)
|
||
|
{
|
||
|
T[] newItems = new T[value];
|
||
|
|
||
|
if (size > 0)
|
||
|
Array.Copy(items, 0, newItems, 0, size);
|
||
|
|
||
|
items = newItems;
|
||
|
}
|
||
|
else
|
||
|
items = emptyArray;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int Count
|
||
|
{
|
||
|
get { return size; }
|
||
|
}
|
||
|
|
||
|
public T this[int index]
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if ((uint)index >= (uint)size)
|
||
|
throw new ArgumentOutOfRangeException();
|
||
|
|
||
|
return items[index];
|
||
|
}
|
||
|
|
||
|
set
|
||
|
{
|
||
|
if ((uint)index >= (uint)size)
|
||
|
throw new ArgumentOutOfRangeException();
|
||
|
|
||
|
items[index] = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Add(T item)
|
||
|
{
|
||
|
if (size == items.Length)
|
||
|
EnsureCapacity(size + 1);
|
||
|
|
||
|
items[size++] = item;
|
||
|
}
|
||
|
|
||
|
public void AddRange(IEnumerable<T> enumerable)
|
||
|
{
|
||
|
if (enumerable == null)
|
||
|
throw new ArgumentNullException("enumerable");
|
||
|
|
||
|
ICollection<T> collection = enumerable as ICollection<T>;
|
||
|
|
||
|
if (collection != null)
|
||
|
{
|
||
|
int count = collection.Count;
|
||
|
|
||
|
if (count > 0)
|
||
|
{
|
||
|
EnsureCapacity(size + count);
|
||
|
|
||
|
collection.CopyTo(items, size);
|
||
|
|
||
|
size += count;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
foreach (var item in enumerable)
|
||
|
Add(item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void AddRange(T[] data, int offset, int count)
|
||
|
{
|
||
|
if (data == null)
|
||
|
throw new ArgumentNullException("data");
|
||
|
|
||
|
if (offset < 0)
|
||
|
throw new ArgumentOutOfRangeException("offset");
|
||
|
|
||
|
if(count < 0)
|
||
|
throw new ArgumentOutOfRangeException("count");
|
||
|
|
||
|
if (data.Length - offset < count)
|
||
|
throw new ArgumentOutOfRangeException("data, offset, count");
|
||
|
|
||
|
if(count > 0)
|
||
|
{
|
||
|
EnsureCapacity(size + count);
|
||
|
|
||
|
Array.Copy(data, offset, items, size, count);
|
||
|
|
||
|
size += count;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void AddRange(T[] data)
|
||
|
{
|
||
|
AddRange(data, 0, data.Length);
|
||
|
}
|
||
|
|
||
|
public void Clear()
|
||
|
{
|
||
|
if (size > 0)
|
||
|
{
|
||
|
Array.Clear(items, 0, size);
|
||
|
size = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool Contains(T item)
|
||
|
{
|
||
|
if ((Object)item == null)
|
||
|
{
|
||
|
for (int i = 0; i < size; i++)
|
||
|
if ((Object)items[i] == null)
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
|
||
|
|
||
|
for (int i = 0; i < size; i++)
|
||
|
{
|
||
|
if (comparer.Equals(items[i], item))
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void CopyTo(T[] array)
|
||
|
{
|
||
|
CopyTo(array, 0);
|
||
|
}
|
||
|
|
||
|
public void CopyTo(int index, T[] array, int arrayIndex, int count)
|
||
|
{
|
||
|
if (size - index < count)
|
||
|
throw new ArgumentException();
|
||
|
|
||
|
Array.Copy(items, index, array, arrayIndex, count);
|
||
|
}
|
||
|
|
||
|
public void CopyTo(T[] array, int arrayIndex)
|
||
|
{
|
||
|
Array.Copy(items, 0, array, arrayIndex, size);
|
||
|
}
|
||
|
|
||
|
|
||
|
private void EnsureCapacity(int min)
|
||
|
{
|
||
|
if (items.Length < min)
|
||
|
{
|
||
|
int newCapacity = items.Length == 0 ? DefaultCapacity : items.Length * 2;
|
||
|
|
||
|
if ((uint)newCapacity > MaxArrayLength)
|
||
|
newCapacity = MaxArrayLength;
|
||
|
|
||
|
if (newCapacity < min)
|
||
|
newCapacity = min;
|
||
|
|
||
|
Capacity = newCapacity;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
public int IndexOf(T item)
|
||
|
{
|
||
|
return Array.IndexOf(items, item, 0, size);
|
||
|
}
|
||
|
|
||
|
public int IndexOf(T item, int index)
|
||
|
{
|
||
|
if (index > size)
|
||
|
throw new ArgumentOutOfRangeException("index");
|
||
|
|
||
|
return Array.IndexOf(items, item, index, size - index);
|
||
|
}
|
||
|
|
||
|
public int IndexOf(T item, int index, int count)
|
||
|
{
|
||
|
if (index > size)
|
||
|
throw new ArgumentOutOfRangeException("index");
|
||
|
|
||
|
if (count < 0 || index > size - count)
|
||
|
throw new ArgumentOutOfRangeException("count");
|
||
|
|
||
|
return Array.IndexOf(items, item, index, count);
|
||
|
}
|
||
|
|
||
|
public bool Remove(T item)
|
||
|
{
|
||
|
int index = IndexOf(item);
|
||
|
|
||
|
if (index >= 0)
|
||
|
{
|
||
|
RemoveAt(index);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public void RemoveAt(int index)
|
||
|
{
|
||
|
if ((uint)index >= (uint)size)
|
||
|
throw new ArgumentOutOfRangeException();
|
||
|
|
||
|
size--;
|
||
|
|
||
|
if (index < size)
|
||
|
{
|
||
|
Array.Copy(items, index + 1, items, index, size - index);
|
||
|
}
|
||
|
|
||
|
items[size] = default(T);
|
||
|
}
|
||
|
|
||
|
public void RemoveRange(int index, int count)
|
||
|
{
|
||
|
if (index < 0)
|
||
|
throw new ArgumentOutOfRangeException("index");
|
||
|
|
||
|
if (count < 0)
|
||
|
throw new ArgumentOutOfRangeException("count");
|
||
|
|
||
|
if (size - index < count)
|
||
|
throw new ArgumentOutOfRangeException();
|
||
|
|
||
|
if (count > 0)
|
||
|
{
|
||
|
size -= count;
|
||
|
|
||
|
if (index < size)
|
||
|
Array.Copy(items, index + count, items, index, size - index);
|
||
|
|
||
|
Array.Clear(items, size, count);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public T[] ToArray()
|
||
|
{
|
||
|
var array = new T[size];
|
||
|
|
||
|
CopyTo(array);
|
||
|
|
||
|
return array;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 获得原始的数组。特别注意:不要对此数组进行操作。
|
||
|
/// </summary>
|
||
|
public T[] GetBuffer()
|
||
|
{
|
||
|
return items;
|
||
|
}
|
||
|
|
||
|
public void TrimExcess()
|
||
|
{
|
||
|
int threshold = (int)(((double)items.Length) * 0.9);
|
||
|
|
||
|
if (size < threshold)
|
||
|
Capacity = size;
|
||
|
}
|
||
|
}
|
||
|
}
|