using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace Cobilas.Collections.Generic {
/// Represents a long, strongly typed list of objects that can be accessed by index.
/// Provides methods for searching, sorting, and manipulating lists.
/// The type of elements in the list.
[Serializable]
public class LongList : ILongList, IReadOnlyLongList, ILongList, ICloneable {
private long _size;
private T[] longArray;
[NonSerialized]
private object _syncRoot;
///
public long Count => _size;
/// Gets or sets the total number of elements the internal data structure can hold without resizing.
public long Capacity {
get => ArrayManipulation.ArrayLongLength(longArray);
set {
if (value < _size)
throw new ArgumentOutOfRangeException("The capacity cannot be smaller than the list size.");
if (value != ArrayManipulation.ArrayLongLength(longArray)) {
if (value > 0) {
T[] newArray = new T[value];
if (_size > 0)
ArrayManipulation.CopyTo(longArray, 0L, newArray, 0L, _size);
longArray = newArray;
} else longArray = Array.Empty();
}
}
}
///
public bool IsReadOnly => false;
bool ILongList.IsFixedSize => false;
bool ILongCollection.IsSynchronized => false;
object ILongCollection.SyncRoot {
get {
if (_syncRoot == null)
Interlocked.CompareExchange(ref _syncRoot, new object(), null);
return _syncRoot;
}
}
///
public T this[long index] { get => longArray[index]; set => longArray[index] = value; }
object ILongList.this[long index] { get => longArray[index]; set => longArray[index] = (T)value; }
/// Creates a new instance of the object.
public LongList() => longArray = Array.Empty();
/// Creates a new instance of the object.
public LongList(long capacity) => longArray = new T[capacity];
/// Creates a new instance of the object.
public LongList(IEnumerable collection) {
foreach (T item in collection) Add(item);
}
/// Creates a new instance of the object.
public LongList(params T[] collection) : this((IEnumerable)collection) {}
/// Returns a read-only ReadOnlyLongCollection< T > wrapper for the current collection.
public ReadOnlyLongCollection AsReadOnly() {
T[] newArray = new T[_size];
CopyTo(newArray, 0L);
return new ReadOnlyLongCollection(newArray);
}
/// Creates a shallow copy of a range of elements in the source .
/// The zero-based index at which the range starts.
/// The number of elements in the range.
///
/// A shallow copy of a range of elements in the source .
public LongList GetRange(long index, long count) {
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException("index", new ArgumentOutOfRangeException());
else if (count < 0 || count > Count)
throw new ArgumentOutOfRangeException("count", new ArgumentOutOfRangeException());
LongList clone = new LongList(count);
ArrayManipulation.CopyTo(longArray, index, clone.longArray, 0L, count);
clone._size = count;
return clone;
}
///
public void Add(T item) {
if (_size == Capacity) Capacity = _size + 1;
longArray[_size++] = item;
}
/// Adds the elements of the specified collection to the end of the .
/// The collection whose elements should be added to the end of the .
/// The collection itself cannot be null , but it can contain elements that are null , if type T is a
/// reference type.
public void AddRange(IEnumerable collection) {
foreach (T item in collection)
Add(item);
}
///
public void Clear() {
ArrayManipulation.LongClearArraySafe(longArray);
_size = 0;
}
///
public bool Contains(T item) => ArrayManipulation.Exists(item, longArray);
///
/// The match parameter allows you to create custom comparison logic.
public bool Contains(Predicate match) => ArrayManipulation.Exists(longArray, match);
///
public void CopyTo(T[] array, long arrayIndex)
=> ArrayManipulation.CopyTo(longArray, arrayIndex, array, arrayIndex, Count);
///
public IEnumerator GetEnumerator() {
T[] newArray = new T[_size];
CopyTo(newArray, 0L);
return new ArrayToIEnumerator(newArray);
}
///
public long IndexOf(T item) => ArrayManipulation.IndexOf(item, longArray);
///
public void Insert(long index, T item) {
ArrayManipulation.Insert(item, index, ref longArray);
_size++;
}
/// Inserts the elements of a collection into the at the specified index.
/// The zero-based index at which the new elements should be inserted.
/// The collection whose elements should be inserted into the .
/// The collection itself cannot be null , but it can contain elements that are null ,
/// if type T is a reference type.
public void InsertRange(long index, IEnumerable collection) {
foreach (T item in collection)
Insert(index, item);
}
///
public bool Remove(T item) {
long index = IndexOf(item);
if (index != -1) RemoveAt(index);
return false;
}
///
public void RemoveAt(long index) {
long old_capacity = Capacity;
ArrayManipulation.Remove(index, ref longArray);
_size--;
Capacity = old_capacity;
}
/// Removes all the elements that match the conditions defined by the specified predicate.
/// The delegate that defines the conditions of the elements to remove.
///
/// The number of elements removed from the .
public long RemoveAll(Predicate match) {
if (match == null)
throw new ArgumentNullException("match", new ArgumentNullException());
long freeIndex = 0;
while( freeIndex < _size && !match(longArray[freeIndex])) freeIndex++;
if( freeIndex >= _size) return 0;
long current = freeIndex + 1;
while( current < _size) {
while( current < _size && match(longArray[current])) current++;
if ( current < _size)
longArray[freeIndex++] = longArray[current++];
}
ArrayManipulation.ClearArray(longArray, freeIndex, _size - freeIndex);
long result = _size - freeIndex;
_size = freeIndex;
return result;
}
/// Removes a range of elements from the
/// The zero-based starting index of the range of elements to remove.
/// The number of elements to remove.
public void RemoveRamge(long index, long count) {
long old_capacity = Capacity;
ArrayManipulation.Remove(index, count, ref longArray);
_size -= count;
Capacity = old_capacity;
}
///
public object Clone() => new LongList(longArray);
/// Copies the elements of the to a new array.
///
public T[] ToArray() {
T[] newArray = new T[_size];
CopyTo(newArray, 0L);
return newArray;
}
///
public void Reverse(long index, long length)
=> ArrayManipulation.Reverse(longArray, index, length);
///
public void Reverse() => Reverse(0L, Count);
///
public T Find(Predicate match)
=> ArrayManipulation.Find(longArray, match);
///
public T FindLast(Predicate match)
=> ArrayManipulation.FindLast(longArray, match);
///
public T[] FindAll(Predicate match)
=> ArrayManipulation.FindAll(longArray, match);
///
public long FindIndex(Predicate match)
=> ArrayManipulation.LongFindIndex(longArray, match);
///
public long FindIndex(long startIndex, Predicate match)
=> ArrayManipulation.FindIndex(longArray, startIndex, match);
///
public long FindIndex(long startIndex, long count, Predicate match)
=> ArrayManipulation.FindIndex(longArray, startIndex, count, match);
///
public long FindLastIndex(Predicate match)
=> ArrayManipulation.LongFindLastIndex(longArray, match);
///
public long FindLastIndex(long startIndex, Predicate match)
=> ArrayManipulation.FindLastIndex(longArray, startIndex, match);
///
public long FindLastIndex(long startIndex, long count, Predicate match)
=> ArrayManipulation.FindLastIndex(longArray, startIndex, count, match);
///
public TOutput[] ConvertAll(Converter converter)
=> ArrayManipulation.LongConvertAll(longArray, converter);
/// Performs the specified action on each element of the .
/// The delegate to perform on each element of the .
///
///
public void ForEach(Action action) {
if (action == null)
throw new ArgumentNullException($"Action<{typeof(T)}> action", new ArgumentNullException());
long _version = longArray.GetHashCode();
foreach (T item in longArray) {
if (_version != longArray.GetHashCode())
throw new InvalidOperationException("The list cannot be changed while executing the ForEach function.");
action(item);
}
}
long ILongList.Add(object value) {
Add((T)value);
return _size - 1;
}
bool ILongList.Contains(object value) => ArrayManipulation.Exists((T)value, longArray);
void ILongCollection.CopyTo(Array array, long index)
=> ArrayManipulation.CopyTo(longArray, index, array, index, Count);
IEnumerator IEnumerable.GetEnumerator() {
T[] newArray = new T[_size];
CopyTo(newArray, 0L);
return new ArrayToIEnumerator(newArray);
}
long ILongList.IndexOf(object value) => IndexOf((T)value);
void ILongList.Insert(long index, object value) => Insert(index, (T)value);
void ILongList.Remove(object value) => Remove((T)value);
}
}