//
// Created by Eugeny Grishul
//
// See license at http://bamelg.com/license.txt
//
namespace System.Collections {
public class List<T> {
private T[] _items;
private int _count, _version;
public List() {
_items = new[16] T;
}
public List( int capacity ) {
_items = new[capacity] T;
}
public List( T* source, int capacity )
: this( capacity ) {
AddRange( source, capacity );
}
public List( List<T> source )
: this( source.GetBuffer(), source.Count ) {
}
public void Add( T item ) {
if( _count == _items.Length )
EnsureCapacity( _count + 1 );
_items[_count++] = item;
CommonCollectionOperations.UpdateVersion( &_version );
}
public void AddRange( T* items, int count ) {
EnsureCapacity( _count + count );
CommonCollectionOperations.Copy<T>( &_items[_count], items, count );
_count += count;
CommonCollectionOperations.UpdateVersion( &_version );
}
public void AddRange( List<T> values ) { AddRange( values.GetBuffer(), values.Count ); }
public void Insert( int index, T item ) {
if( !Assert.IsFalse( index > _count ) ) return;
if( _count == _items.Length )
EnsureCapacity( _count + 1 );
if( index < _count )
CommonCollectionOperations.Copy<T>( &_items[index + 1], &_items[index], _count - index );
_items[index] = item;
++_count;
CommonCollectionOperations.UpdateVersion( &_version );
}
public void Clear() {
CommonCollectionOperations.Clear<T>( &_items[0], _count );
_count = 0;
CommonCollectionOperations.UpdateVersion( &_version );
}
public int Count { get { return _count; } }
public T this[int index] {
get { return _items[index]; }
set { _items[index] = value; }
}
public void Reserve( int newCount ) {
if( newCount <= _count ) return;
if( newCount < _items.Length ) {
_count = newCount;
return;
}
EnsureCapacity( newCount );
_count = newCount;
}
public int Capacity {
get {
return ( int ) _items.Length;
}
set {
if( value != _items.Length ) {
if( !Assert.IsFalse( value < _count ) )
return;
if( value > 0 ) {
var destinationArray = new[value] T;
CommonCollectionOperations.Copy<T>( &destinationArray[0], &_items[0], _count );
_items = destinationArray;
}
}
}
}
public int IndexOf( T value ) {
for( int i = 0; i < _count; ++i )
if( _items[i] == value ) return i;
return -1;
}
public bool Contains( T value ) { return IndexOf( value ) != -1; }
public int LastIndexOf( T value ) {
for( int i = _count - 1; i >= 0; --i )
if( _items[i] == value ) return i;
return -1;
}
public int IndexOf( T value, int startIndex ) {
if( !Assert.IsFalse( startIndex < 0 | startIndex >= _count ) )
return -1;
for( int i = startIndex; i < _count; ++i )
if( _items[i] == value ) return i;
return -1;
}
public int LastIndexOf( T value, int startIndex ) {
if( !Assert.IsFalse( startIndex < 0 | startIndex >= _count ) )
return -1;
for( int i = _count - 1; i >= startIndex; --i )
if( _items[i] == value ) return i;
return -1;
}
public int IndexOf( T value, int startIndex, int count ) {
if( !Assert.IsFalse( startIndex < 0 | startIndex >= _count ) )
return -1;
if( !Assert.IsFalse( count < 0 | startIndex + count > _count ) )
return -1;
for( int i = startIndex; i < _count; ++i )
if( _items[i] == value ) return i;
return -1;
}
public int LastIndexOf( T value, int startIndex, int count ) {
if( !Assert.IsFalse( startIndex < 0 | startIndex >= _count ) )
return -1;
if( !Assert.IsFalse( count < 0 | startIndex + count > _count ) )
return -1;
for( int i = _count - 1; i >= startIndex | count > 0; --i, --count )
if( _items[i] == value ) return i;
return -1;
}
public void RemoveAt( int index ) {
RemoveAt( index, 1 );
}
public void RemoveAt( int index, int count ) {
if( !Assert.IsFalse( index < 0 || index >= _count ) )
return;
if( !Assert.IsFalse( count < 0 || index + count > _count ) )
return;
_count -= count;
if( index < _count )
CommonCollectionOperations.Copy<T>( &_items[index], &_items[index + count], _count - index );
CommonCollectionOperations.Clear<T>( &_items[_count], count );
CommonCollectionOperations.UpdateVersion( &_version );
}
public bool Remove( T item ) {
var index = IndexOf( item );
if( index >= 0 ) {
RemoveAt( index );
return true;
}
return false;
}
public void Reverse() {
for( int i = 0; i < _count / 2; ++i )
CommonCollectionOperations.Swap<T>( _items[i], _items[_count - i - 1] );
}
public T[] ToArray() {
var result = new[_count] T;
CommonCollectionOperations.Copy<T>( &result[0], &_items[0], _count );
return result;
}
// Result will be invalid after resizing
public T* GetBuffer() {
return &_items[0];
}
private void EnsureCapacity( int recommendedCapacity ) {
if( _items.Length >= recommendedCapacity ) return;
Capacity = Math.Max( _items.Length * 2, ( int ) recommendedCapacity );
}
public void RemoveRange( int startIndex, int length ) {
if( !Assert.IsFalse( startIndex < 0 | startIndex > _count ) )
return;
if( !Assert.IsFalse( length < 0 | startIndex > _count - length ) )
return;
CommonCollectionOperations.Copy<T>( &_items[startIndex], &_items[startIndex + length], _count - length - startIndex );
_count -= length;
}
public Enumerator GetEnumerator() {
return new Enumerator( this );
}
[EnumeratorAttribute]
public struct Enumerator {
private readonly declaringtype _parent;
private readonly int _version;
private int _index;
internal Enumerator( declaringtype parent ) {
_index = -1;
_parent = parent;
_version = parent._version;
}
public bool MoveNext() {
CommonCollectionOperations.VersionCheck( _version == _parent._version );
return ++_index < _parent.Count;
}
public T Current { get { return _parent[_index]; } }
}
}
}