// Copyright (c) 2012 DotNetAnywhere
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
#if LOCALTEST
using System.Collections;
using System.Collections.Generic;
namespace System_.Collections.Generic {
#else
namespace System.Collections.Generic {
#endif
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable {
public struct Enumerator : IEnumerator<T>, IDisposable {
private List<T> list;
private int index;
internal Enumerator(List<T> list) {
this.list = list;
this.index = -1;
}
public T Current {
get {
return this.list[this.index];
}
}
public void Dispose() {
}
object IEnumerator.Current {
get {
return this.list[this.index];
}
}
public bool MoveNext() {
this.index++;
return (this.index < this.list.Count);
}
public void Reset() {
this.index = -1;
}
}
private const int defaultCapacity = 4;
private T[] items;
private int size;
public List() : this(defaultCapacity) { }
public List(int capacity) {
if (capacity < 0) {
throw new ArgumentOutOfRangeException("capacity");
}
this.items = new T[capacity];
this.size = 0;
}
public List(IEnumerable<T> collection) {
ICollection<T> iCol = collection as ICollection<T>;
if (iCol != null) {
this.size = iCol.Count;
this.items = new T[this.size];
iCol.CopyTo(this.items, 0);
} else {
this.items = new T[defaultCapacity];
this.size = 0;
foreach (T item in collection) {
this.Add(item);
}
}
}
private void EnsureSpace(int space) {
if (this.size + space > this.items.Length) {
Array.Resize<T>(ref this.items, Math.Max(this.items.Length << 1, 4));
}
}
private void Shift(int index, int count) {
if (count > 0) {
this.EnsureSpace(count);
for (int i = this.size - 1; i >= index; i--) {
this.items[i + count] = this.items[i];
}
} else {
for (int i = index; i < this.size + count; i++) {
this.items[i] = this.items[i - count];
}
}
this.size += count;
}
public void Add(T item) {
this.EnsureSpace(1);
this.items[this.size++] = item;
}
public int Count {
get {
return this.size;
}
}
public int Capacity {
get {
return this.items.Length;
}
set {
throw new NotImplementedException();
}
}
public T this[int index] {
get {
if (index >= this.size || index < 0) {
throw new ArgumentOutOfRangeException("index");
}
return this.items[index];
}
set {
if (index >= this.size || index < 0) {
throw new ArgumentOutOfRangeException("index");
}
this.items[index] = value;
}
}
public Enumerator GetEnumerator() {
return new Enumerator(this);
}
public int IndexOf(T item, int start, int count) {
return Array.IndexOf<T>(this.items, item, start, count);
}
public int IndexOf(T item, int start) {
return this.IndexOf(item, start, this.size - start);
}
public void InsertRange(int index, IEnumerable<T> collection) {
if (collection == null) {
throw new ArgumentNullException("collection");
}
if (index < 0 || index > this.size) {
throw new ArgumentOutOfRangeException("index");
}
List<T> toInsert = new List<T>(collection);
this.Shift(index, toInsert.Count);
for (int i = 0; i < toInsert.Count; i++) {
this.items[index + i] = toInsert[i];
}
}
public T[] ToArray() {
T[] array = new T[this.size];
Array.Copy(this.items, array, this.size);
return array;
}
#region Interface Members
public int IndexOf(T item) {
return this.IndexOf(item, 0, size);
}
public void Insert(int index, T item) {
if (index < 0 || index > this.size) {
throw new ArgumentOutOfRangeException("index");
}
this.Shift(index, 1);
this.items[index] = item;
}
public void RemoveAt(int index) {
this.Shift(index, -1);
}
public bool IsReadOnly {
get {
return false;
}
}
public void Clear() {
Array.Clear(this.items, 0, this.items.Length);
this.size = 0;
}
public bool Contains(T item) {
return Array.IndexOf(this.items, item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex) {
Array.Copy(this.items, 0, (Array)array, arrayIndex, this.size);
}
public bool Remove(T item) {
int idx = Array.IndexOf(this.items, item);
if (idx >= 0) {
this.RemoveAt(idx);
return true;
}
return false;
}
IEnumerator<T> IEnumerable<T>.GetEnumerator() {
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator() {
return new Enumerator(this);
}
public bool IsFixedSize {
get {
return false;
}
}
object IList.this[int index] {
get {
return this[index];
}
set {
this[index] = (T)value;
}
}
public int Add(object value) {
this.Add((T)value);
return this.items.Length - 1;
}
public bool Contains(object value) {
return this.Contains((T)value);
}
public int IndexOf(object value) {
return this.IndexOf((T)value);
}
public void Insert(int index, object value) {
this.Insert(index, (T)value);
}
public void Remove(object value) {
this.Remove((T)value);
}
public bool IsSynchronized {
get {
return false;
}
}
public object SyncRoot {
get {
return this;
}
}
public void CopyTo(Array array, int index) {
Array.Copy(this.items, 0, array, index, this.size);
}
#endregion
}
}