diff --git a/spine-csharp/src/ExposedList.cs b/spine-csharp/src/ExposedList.cs
index 03eaa6c23..62b1ed1f4 100644
--- a/spine-csharp/src/ExposedList.cs
+++ b/spine-csharp/src/ExposedList.cs
@@ -1,702 +1,583 @@
-using System;
+//
+// System.Collections.Generic.List
+//
+// Authors:
+// Ben Maurer (bmaurer@ximian.com)
+// Martin Baulig (martin@ximian.com)
+// Carlos Alberto Cortez (calberto.cortez@gmail.com)
+// David Waite (mass@akuma.org)
+//
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005 David Waite
+//
+// 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;
+using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics;
namespace Spine {
- ///
- /// Represents a strongly typed list of objects that can be accessed by index. Provides methods to search and manipulate lists.
- ///
- /// The type of elements in the list.
- public class ExposedList : IEnumerable {
- private const int defaultCapacity = 4;
- private static readonly T[] emptyArray = new T[0];
- public T[] Items;
+ [Serializable]
+ [DebuggerDisplay("Count={Count}")]
+ public class ExposedList : IEnumerable {
+ public T[] Items;
+ public int Count;
- private int size;
+ private const int DefaultCapacity = 4;
+ private static readonly T[] EmptyArray = new T[0];
+ private int _version;
- ///
- /// Initializes a new instance of the class that is empty and has the default initial capacity.
- ///
- public ExposedList() {
- Items = emptyArray;
- }
+ public ExposedList() {
+ Items = EmptyArray;
+ }
- ///
- /// Initializes a new instance of the class that is empty and has the specified initial capacity.
- ///
- /// The number of elements that the new list can initially store.
- ///
- /// is less than 0.
- ///
- public ExposedList(int capacity) {
- if (capacity < 0) {
- throw new ArgumentOutOfRangeException("capacity");
- }
- Items = new T[capacity];
- }
+ public ExposedList(IEnumerable collection) {
+ CheckCollection(collection);
-
- // Constructs a List, copying the contents of the given collection. The
- // size and capacity of the new list will both be equal to the size of the
- // given collection.
- //
- public ExposedList(IEnumerable collection) {
- if (collection==null)
- throw new ArgumentNullException("collection");
+ // initialize to needed size (if determinable)
+ ICollection c = collection as ICollection;
+ if (c == null) {
+ Items = EmptyArray;
+ AddEnumerable(collection);
+ } else {
+ Items = new T[c.Count];
+ AddCollection(c);
+ }
+ }
- ICollection c = collection as ICollection;
- if( c != null) {
- int count = c.Count;
- Items = new T[count];
- c.CopyTo(Items, 0);
- size = count;
- }
- else {
- size = 0;
- Items = new T[defaultCapacity];
+ public ExposedList(int capacity) {
+ if (capacity < 0)
+ throw new ArgumentOutOfRangeException("capacity");
+ Items = new T[capacity];
+ }
- using(IEnumerator en = collection.GetEnumerator()) {
- while(en.MoveNext()) {
- Add(en.Current);
- }
- }
- }
- }
+ internal ExposedList(T[] data, int size) {
+ Items = data;
+ Count = size;
+ }
- ///
- /// Gets or sets the total number of elements the internal data structure can hold without resizing.
- ///
- ///
- /// The number of elements that the can contain before resizing is required.
- ///
- ///
- /// is set to a value that is less than
- ///
- /// .
- ///
- /// There is not enough memory available on the system.
- public int Capacity {
- get {
- return Items.Length;
- }
- set {
- if (value == Items.Length) {
- return;
- }
- if (value < size) {
- throw new ArgumentOutOfRangeException("value");
- }
- if (value > 0) {
- var objArray = new T[value];
- if (size > 0) {
- Array.Copy(Items, 0, objArray, 0, size);
- }
- Items = objArray;
- } else {
- Items = emptyArray;
- }
- }
- }
+ public void Add(T item) {
+ // If we check to see if we need to grow before trying to grow
+ // we can speed things up by 25%
+ if (Count == Items.Length)
+ GrowIfNeeded(1);
+ Items[Count ++] = item;
+ _version++;
+ }
- ///
- /// Gets the number of elements actually contained in the .
- ///
- ///
- /// The number of elements actually contained in the .
- ///
- public int Count {
- get {
- return size;
- }
- }
+ private void GrowIfNeeded(int newCount) {
+ int minimumSize = Count + newCount;
+ if (minimumSize > Items.Length)
+ Capacity = Math.Max(Math.Max(Capacity * 2, DefaultCapacity), minimumSize);
+ }
- ///
- /// Adds an object to the end of the .
- ///
- ///
- /// The object to be added to the end of the . The value can be null for reference types.
- ///
- public void Add(T item) {
- if (size == Items.Length) {
- EnsureCapacity(size + 1);
- }
- Items[size++] = item;
- }
+ private void CheckRange(int idx, int count) {
+ if (idx < 0)
+ throw new ArgumentOutOfRangeException("index");
- ///
- /// Removes all elements from the .
- ///
- public void Clear() {
- if (size > 0) {
- Array.Clear(Items, 0, size);
- size = 0;
- }
- }
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count");
- ///
- /// Determines whether an element is in the .
- ///
- ///
- /// true if is found in the ; otherwise, false.
- ///
- ///
- /// The object to locate in the . The value can be null for reference types.
- ///
- public bool Contains(T item) {
- if (item == null) {
- for (int index = 0; index < size; ++index) {
- if (Items[index] == null) {
- return true;
- }
- }
- return false;
- } else {
- EqualityComparer @default = EqualityComparer.Default;
- for (int index = 0; index < size; ++index) {
- if (@default.Equals(Items[index], item)) {
- return true;
- }
- }
- return false;
- }
- }
+ if ((uint) idx + (uint) count > (uint) Count)
+ throw new ArgumentException("index and count exceed length of list");
+ }
- ///
- /// Copies the entire to a compatible one-dimensional array, starting at the specified index of the target array.
- ///
- ///
- /// The one-dimensional that is the destination of the elements copied from
- ///
- /// . The must have zero-based indexing.
- ///
- ///
- /// The zero-based index in at which copying begins.
- ///
- ///
- /// is null.
- ///
- ///
- /// is less than 0.
- ///
- ///
- /// The number of elements in the source is greater than the available space from
- ///
- /// to the end of the destination .
- ///
- public void CopyTo(T[] array, int arrayIndex) {
- Array.Copy(Items, 0, array, arrayIndex, size);
- }
+ private void AddCollection(ICollection collection) {
+ int collectionCount = collection.Count;
+ if (collectionCount == 0)
+ return;
- ///
- /// Searches for the specified object and returns the zero-based index of the first occurrence within the entire
- ///
- /// .
- ///
- ///
- /// The zero-based index of the first occurrence of within the entire
- ///
- /// , if found; otherwise, –1.
- ///
- ///
- /// The object to locate in the . The value can be null for reference types.
- ///
- public int IndexOf(T item) {
- return Array.IndexOf(Items, item, 0, size);
- }
+ GrowIfNeeded(collectionCount);
+ collection.CopyTo(Items, Count);
+ Count += collectionCount;
+ }
- ///
- /// Inserts an element into the at the specified index.
- ///
- ///
- /// The zero-based index at which should be inserted.
- ///
- /// The object to insert. The value can be null for reference types.
- ///
- /// is less than 0.-or- is greater than
- ///
- /// .
- ///
- public void Insert(int index, T item) {
- if ((uint) index > (uint) size) {
- throw new ArgumentOutOfRangeException("index");
- }
- if (size == Items.Length) {
- EnsureCapacity(size + 1);
- }
- if (index < size) {
- Array.Copy(Items, index, Items, index + 1, size - index);
- }
- Items[index] = item;
- ++size;
- }
+ private void AddEnumerable(IEnumerable enumerable) {
+ foreach (T t in enumerable) {
+ Add(t);
+ }
+ }
- ///
- /// Removes the first occurrence of a specific object from the .
- ///
- ///
- /// true if is successfully removed; otherwise, false. This method also returns false if
- ///
- /// was not found in the .
- ///
- ///
- /// The object to remove from the . The value can be null for reference types.
- ///
- public bool Remove(T item) {
- int index = IndexOf(item);
- if (index < 0) {
- return false;
- }
- RemoveAt(index);
- return true;
- }
+ public void AddRange(IEnumerable collection) {
+ CheckCollection(collection);
- ///
- /// Removes the element at the specified index of the .
- ///
- /// The zero-based index of the element to remove.
- ///
- /// is less than 0.-or- is equal to or greater than
- ///
- /// .
- ///
- 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);
- }
+ ICollection c = collection as ICollection;
+ if (c != null)
+ AddCollection(c);
+ else
+ AddEnumerable(collection);
+ _version++;
+ }
- ///
- /// Copies the entire to a compatible one-dimensional array, starting at the beginning of the target array.
- ///
- ///
- /// The one-dimensional that is the destination of the elements copied from
- ///
- /// . The must have zero-based indexing.
- ///
- ///
- /// is null.
- ///
- ///
- /// The number of elements in the source is greater than the number of elements that the destination
- ///
- /// can contain.
- ///
- public void CopyTo(T[] array) {
- CopyTo(array, 0);
- }
+ public int BinarySearch(T item) {
+ return Array.BinarySearch(Items, 0, Count, item);
+ }
- ///
- /// Copies a range of elements from the to a compatible one-dimensional array, starting at the specified index of the target array.
- ///
- ///
- /// The zero-based index in the source at which copying begins.
- ///
- ///
- /// The one-dimensional that is the destination of the elements copied from
- ///
- /// . The must have zero-based indexing.
- ///
- ///
- /// The zero-based index in at which copying begins.
- ///
- /// The number of elements to copy.
- ///
- /// is null.
- ///
- ///
- /// is less than 0.-or- is less than 0.-or-
- ///
- /// is less than 0.
- ///
- ///
- /// is equal to or greater than the of the source
- ///
- /// .-or-The number of elements from to the end of the source
- ///
- /// is greater than the available space from
- ///
- /// to the end of the destination .
- ///
- public void CopyTo(int index, T[] array, int arrayIndex, int count) {
- if (size - index < count) {
- throw new ArgumentException("Invalid length");
- }
- Array.Copy(Items, index, array, arrayIndex, count);
- }
+ public int BinarySearch(T item, IComparer comparer) {
+ return Array.BinarySearch(Items, 0, Count, item, comparer);
+ }
- private void EnsureCapacity(int min) {
- if (Items.Length >= min) {
- return;
- }
- int num = Items.Length == 0 ? 4 : Items.Length * 2;
- if (num < min) {
- num = min;
- }
- Capacity = num;
- }
+ public int BinarySearch(int index, int count, T item, IComparer comparer) {
+ CheckRange(index, count);
+ return Array.BinarySearch(Items, index, count, item, comparer);
+ }
- ///
- /// Creates a shallow copy of a range of elements in the source .
- ///
- ///
- /// 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.
- ///
- /// is less than 0.-or- is less than 0.
- ///
- ///
- /// and do not denote a valid range of elements in the
- ///
- /// .
- ///
- public ExposedList GetRange(int index, int count) {
- if (index < 0 || count < 0) {
- throw new ArgumentOutOfRangeException("index || count");
- }
- if (size - index < count) {
- throw new ArgumentException("Invalid length");
- }
- var list = new ExposedList(count);
- Array.Copy(Items, index, list.Items, 0, count);
- list.size = count;
- return list;
- }
+ public void Clear() {
+ Array.Clear(Items, 0, Items.Length);
+ Count = 0;
+ _version++;
+ }
- ///
- /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the
- ///
- /// that extends from the specified index to the last element.
- ///
- ///
- /// The zero-based index of the first occurrence of within the range of elements in the
- ///
- /// that extends from to the last element, if found; otherwise, –1.
- ///
- ///
- /// The object to locate in the . The value can be null for reference types.
- ///
- /// The zero-based starting index of the search. 0 (zero) is valid in an empty list.
- ///
- /// is outside the range of valid indexes for the
- ///
- /// .
- ///
- public int IndexOf(T item, int index) {
- if (index > size) {
- throw new ArgumentOutOfRangeException("index");
- }
- return Array.IndexOf(Items, item, index, size - index);
- }
+ public bool Contains(T item) {
+ return Array.IndexOf(Items, item, 0, Count) != -1;
+ }
- ///
- /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the
- ///
- /// that starts at the specified index and contains the specified number of elements.
- ///
- ///
- /// The zero-based index of the first occurrence of within the range of elements in the
- ///
- /// that starts at and contains
- ///
- /// number of elements, if found; otherwise, –1.
- ///
- ///
- /// The object to locate in the . The value can be null for reference types.
- ///
- /// The zero-based starting index of the search. 0 (zero) is valid in an empty list.
- /// The number of elements in the section to search.
- ///
- /// is outside the range of valid indexes for the
- ///
- /// .-or- is less than 0.-or-
- ///
- /// and do not specify a valid section in the
- ///
- /// .
- ///
- 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 ExposedList ConvertAll(Converter converter) {
+ if (converter == null)
+ throw new ArgumentNullException("converter");
+ ExposedList u = new ExposedList(Count);
+ for (int i = 0; i < Count; i++)
+ u.Items[i] = converter(Items[i]);
- ///
- /// Searches for the specified object and returns the zero-based index of the last occurrence within the entire
- ///
- /// .
- ///
- ///
- /// The zero-based index of the last occurrence of within the entire the
- ///
- /// , if found; otherwise, –1.
- ///
- ///
- /// The object to locate in the . The value can be null for reference types.
- ///
- public int LastIndexOf(T item) {
- return LastIndexOf(item, size - 1, size);
- }
+ u.Count = Count;
+ return u;
+ }
- ///
- /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the
- ///
- /// that extends from the first element to the specified index.
- ///
- ///
- /// The zero-based index of the last occurrence of within the range of elements in the
- ///
- /// that extends from the first element to , if found; otherwise, –1.
- ///
- ///
- /// The object to locate in the . The value can be null for reference types.
- ///
- /// The zero-based starting index of the backward search.
- ///
- /// is outside the range of valid indexes for the
- ///
- /// .
- ///
- public int LastIndexOf(T item, int index) {
- if (index >= size) {
- throw new ArgumentOutOfRangeException("index");
- }
- return LastIndexOf(item, index, index + 1);
- }
+ public void CopyTo(T[] array) {
+ Array.Copy(Items, 0, array, 0, Count);
+ }
- ///
- /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the
- ///
- /// that contains the specified number of elements and ends at the specified index.
- ///
- ///
- /// The zero-based index of the last occurrence of within the range of elements in the
- ///
- /// that contains number of elements and ends at
- ///
- /// , if found; otherwise, –1.
- ///
- ///
- /// The object to locate in the . The value can be null for reference types.
- ///
- /// The zero-based starting index of the backward search.
- /// The number of elements in the section to search.
- ///
- /// is outside the range of valid indexes for the
- ///
- /// .-or- is less than 0.-or-
- ///
- /// and do not specify a valid section in the
- ///
- /// .
- ///
- public int LastIndexOf(T item, int index, int count) {
- if (size == 0) {
- return -1;
- }
- if (index < 0 || count < 0) {
- throw new ArgumentOutOfRangeException("index || count");
- }
- if (index >= size || count > index + 1) {
- throw new ArgumentOutOfRangeException("size || count");
- }
- return Array.LastIndexOf(Items, item, index, count);
- }
+ public void CopyTo(T[] array, int arrayIndex) {
+ Array.Copy(Items, 0, array, arrayIndex, Count);
+ }
- ///
- /// 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.
- ///
- /// is less than 0.-or- is less than 0.
- ///
- ///
- /// and do not denote a valid range of elements in the
- ///
- /// .
- ///
- public void RemoveRange(int index, int count) {
- if (index < 0 || count < 0) {
- throw new ArgumentOutOfRangeException("index || count");
- }
- if (size - index < count) {
- throw new ArgumentException("Invalid length");
- }
- if (count <= 0) {
- return;
- }
- size -= count;
- if (index < size) {
- Array.Copy(Items, index + count, Items, index, size - index);
- }
- Array.Clear(Items, size, count);
- }
+ public void CopyTo(int index, T[] array, int arrayIndex, int count) {
+ CheckRange(index, count);
+ Array.Copy(Items, index, array, arrayIndex, count);
+ }
- public void TrimExcess() {
- int threshold = (int)(((double) Items.Length) * 0.9);
- if( size < threshold ) {
- Capacity = size;
- }
- }
+ public bool Exists(Predicate match) {
+ CheckMatch(match);
+ return GetIndex(0, Count, match) != -1;
+ }
- //public void Sort(Comparison comparison)
- //{
- // if (comparison == null)
- // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
- // if (this.size <= 0)
- // return;
- // Array.Sort(this._items, 0, this.size, (IComparer) new Array.FunctorComparer(comparison));
- //}
+ public T Find(Predicate match) {
+ CheckMatch(match);
+ int i = GetIndex(0, Count, match);
+ return (i != -1) ? Items[i] : default (T);
+ }
- ///
- /// Sorts the elements in the entire using the specified
- ///
- /// .
- ///
- ///
- /// The to use when comparing elements.
- ///
- ///
- /// is null.
- ///
- ///
- /// The implementation of caused an error during the sort. For example,
- ///
- /// might not return 0 when comparing an item with itself.
- ///
- ///
- /// Copies the elements of the to a new array.
- ///
- ///
- /// An array containing copies of the elements of the .
- ///
- public T[] ToArray() {
- var objArray = new T[size];
- Array.Copy(Items, 0, objArray, 0, size);
- return objArray;
- }
+ private static void CheckMatch(Predicate match) {
+ if (match == null)
+ throw new ArgumentNullException("match");
+ }
- // Returns an enumerator for this list with the given
- // permission for removal of elements. If modifications made to the list
- // while an enumeration is in progress, the MoveNext and
- // GetObject methods of the enumerator will throw an exception.
- //
- public Enumerator GetEnumerator() {
- return new Enumerator(this);
- }
+ public ExposedList FindAll(Predicate match) {
+ CheckMatch(match);
+ return FindAllList(match);
+ }
- IEnumerator IEnumerable.GetEnumerator() {
- return new Enumerator(this);
- }
+ private ExposedList FindAllList(Predicate match) {
+ ExposedList results = new ExposedList();
+ for (int i = 0; i < Count; i++)
+ if (match(Items[i]))
+ results.Add(Items[i]);
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
- return new Enumerator(this);
- }
+ return results;
+ }
- [Serializable()]
- public struct Enumerator : IEnumerator, System.Collections.IEnumerator
- {
- private readonly ExposedList list;
- private int index;
- private T current;
-
- internal Enumerator(ExposedList list) {
- this.list = list;
- index = 0;
- current = default(T);
- }
+ public int FindIndex(Predicate match) {
+ CheckMatch(match);
+ return GetIndex(0, Count, match);
+ }
- public void Dispose() {
- }
+ public int FindIndex(int startIndex, Predicate match) {
+ CheckMatch(match);
+ CheckIndex(startIndex);
+ return GetIndex(startIndex, Count - startIndex, match);
+ }
- public bool MoveNext() {
- ExposedList localList = list;
+ public int FindIndex(int startIndex, int count, Predicate match) {
+ CheckMatch(match);
+ CheckRange(startIndex, count);
+ return GetIndex(startIndex, count, match);
+ }
- if (((uint)index < (uint)localList.size)) {
- current = localList.Items[index];
- index++;
- return true;
- }
- return MoveNextRare();
- }
+ private int GetIndex(int startIndex, int count, Predicate match) {
+ int end = startIndex + count;
+ for (int i = startIndex; i < end; i ++)
+ if (match(Items[i]))
+ return i;
- private bool MoveNextRare()
- {
- index = list.size + 1;
- current = default(T);
- return false;
- }
+ return -1;
+ }
- public T Current {
- get {
- return current;
- }
- }
+ public T FindLast(Predicate match) {
+ CheckMatch(match);
+ int i = GetLastIndex(0, Count, match);
+ return i == -1 ? default (T) : Items[i];
+ }
- Object System.Collections.IEnumerator.Current {
- get {
- if( index == 0 || index == list.size + 1)
- throw new InvalidOperationException();
- return Current;
- }
- }
+ public int FindLastIndex(Predicate match) {
+ CheckMatch(match);
+ return GetLastIndex(0, Count, match);
+ }
- void System.Collections.IEnumerator.Reset() {
- index = 0;
- current = default(T);
- }
+ public int FindLastIndex(int startIndex, Predicate match) {
+ CheckMatch(match);
+ CheckIndex(startIndex);
+ return GetLastIndex(0, startIndex + 1, match);
+ }
- }
- }
+ public int FindLastIndex(int startIndex, int count, Predicate match) {
+ CheckMatch(match);
+ int start = startIndex - count + 1;
+ CheckRange(start, count);
+ return GetLastIndex(start, count, match);
+ }
+
+ private int GetLastIndex(int startIndex, int count, Predicate match) {
+ // unlike FindLastIndex, takes regular params for search range
+ for (int i = startIndex + count; i != startIndex;)
+ if (match(Items[--i]))
+ return i;
+ return -1;
+ }
+
+ public void ForEach(Action action) {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ for (int i = 0; i < Count; i++)
+ action(Items[i]);
+ }
+
+ public Enumerator GetEnumerator() {
+ return new Enumerator(this);
+ }
+
+ public ExposedList GetRange(int index, int count) {
+ CheckRange(index, count);
+ T[] tmpArray = new T[count];
+ Array.Copy(Items, index, tmpArray, 0, count);
+ return new ExposedList(tmpArray, count);
+ }
+
+ public int IndexOf(T item) {
+ return Array.IndexOf(Items, item, 0, Count);
+ }
+
+ public int IndexOf(T item, int index) {
+ CheckIndex(index);
+ return Array.IndexOf(Items, item, index, Count - index);
+ }
+
+ public int IndexOf(T item, int index, int count) {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count");
+
+ if ((uint) index + (uint) count > (uint) Count)
+ throw new ArgumentOutOfRangeException("index and count exceed length of list");
+
+ return Array.IndexOf(Items, item, index, count);
+ }
+
+ private void Shift(int start, int delta) {
+ if (delta < 0)
+ start -= delta;
+
+ if (start < Count)
+ Array.Copy(Items, start, Items, start + delta, Count - start);
+
+ Count += delta;
+
+ if (delta < 0)
+ Array.Clear(Items, Count, -delta);
+ }
+
+ private void CheckIndex(int index) {
+ if (index < 0 || (uint) index > (uint) Count)
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ public void Insert(int index, T item) {
+ CheckIndex(index);
+ if (Count == Items.Length)
+ GrowIfNeeded(1);
+ Shift(index, 1);
+ Items[index] = item;
+ _version++;
+ }
+
+ private void CheckCollection(IEnumerable collection) {
+ if (collection == null)
+ throw new ArgumentNullException("collection");
+ }
+
+ public void InsertRange(int index, IEnumerable collection) {
+ CheckCollection(collection);
+ CheckIndex(index);
+ if (collection == this) {
+ T[] buffer = new T[Count];
+ CopyTo(buffer, 0);
+ GrowIfNeeded(Count);
+ Shift(index, buffer.Length);
+ Array.Copy(buffer, 0, Items, index, buffer.Length);
+ } else {
+ ICollection c = collection as ICollection;
+ if (c != null)
+ InsertCollection(index, c);
+ else
+ InsertEnumeration(index, collection);
+ }
+ _version++;
+ }
+
+ private void InsertCollection(int index, ICollection collection) {
+ int collectionCount = collection.Count;
+ GrowIfNeeded(collectionCount);
+
+ Shift(index, collectionCount);
+ collection.CopyTo(Items, index);
+ }
+
+ private void InsertEnumeration(int index, IEnumerable enumerable) {
+ foreach (T t in enumerable)
+ Insert(index++, t);
+ }
+
+ public int LastIndexOf(T item) {
+ return Array.LastIndexOf(Items, item, Count - 1, Count);
+ }
+
+ public int LastIndexOf(T item, int index) {
+ CheckIndex(index);
+ return Array.LastIndexOf(Items, item, index, index + 1);
+ }
+
+ public int LastIndexOf(T item, int index, int count) {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", index, "index is negative");
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", count, "count is negative");
+
+ if (index - count + 1 < 0)
+ throw new ArgumentOutOfRangeException("count", count, "count is too large");
+
+ return Array.LastIndexOf(Items, item, index, count);
+ }
+
+ public bool Remove(T item) {
+ int loc = IndexOf(item);
+ if (loc != -1)
+ RemoveAt(loc);
+
+ return loc != -1;
+ }
+
+ public int RemoveAll(Predicate match) {
+ CheckMatch(match);
+ int i = 0;
+ int j = 0;
+
+ // Find the first item to remove
+ for (i = 0; i < Count; i++)
+ if (match(Items[i]))
+ break;
+
+ if (i == Count)
+ return 0;
+
+ _version++;
+
+ // Remove any additional items
+ for (j = i + 1; j < Count; j++) {
+ if (!match(Items[j]))
+ Items[i++] = Items[j];
+ }
+ if (j - i > 0)
+ Array.Clear(Items, i, j - i);
+
+ Count = i;
+ return (j - i);
+ }
+
+ public void RemoveAt(int index) {
+ if (index < 0 || (uint) index >= (uint) Count)
+ throw new ArgumentOutOfRangeException("index");
+ Shift(index, -1);
+ Array.Clear(Items, Count, 1);
+ _version++;
+ }
+
+ public void RemoveRange(int index, int count) {
+ CheckRange(index, count);
+ if (count > 0) {
+ Shift(index, -count);
+ Array.Clear(Items, Count, count);
+ _version++;
+ }
+ }
+
+ public void Reverse() {
+ Array.Reverse(Items, 0, Count);
+ _version++;
+ }
+
+ public void Reverse(int index, int count) {
+ CheckRange(index, count);
+ Array.Reverse(Items, index, count);
+ _version++;
+ }
+
+ public void Sort() {
+ Array.Sort(Items, 0, Count, Comparer.Default);
+ _version++;
+ }
+
+ public void Sort(IComparer comparer) {
+ Array.Sort(Items, 0, Count, comparer);
+ _version++;
+ }
+
+ public void Sort(Comparison comparison) {
+ Array.Sort(Items, comparison);
+ _version++;
+ }
+
+ public void Sort(int index, int count, IComparer comparer) {
+ CheckRange(index, count);
+ Array.Sort(Items, index, count, comparer);
+ _version++;
+ }
+
+ public T[] ToArray() {
+ T[] t = new T[Count];
+ Array.Copy(Items, t, Count);
+
+ return t;
+ }
+
+ public void TrimExcess() {
+ Capacity = Count;
+ }
+
+ public bool TrueForAll(Predicate match) {
+ CheckMatch(match);
+
+ for (int i = 0; i < Count; i++)
+ if (!match(Items[i]))
+ return false;
+
+ return true;
+ }
+
+ public int Capacity {
+ get {
+ return Items.Length;
+ }
+ set {
+ if ((uint) value < (uint) Count)
+ throw new ArgumentOutOfRangeException();
+
+ Array.Resize(ref Items, value);
+ }
+ }
+
+ #region Interface implementations.
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+
+ #endregion
+
+ [Serializable]
+ public struct Enumerator : IEnumerator, IDisposable {
+ private ExposedList l;
+ private int next;
+ private int ver;
+
+ private T current;
+
+ internal Enumerator(ExposedList l)
+ : this() {
+ this.l = l;
+ ver = l._version;
+ }
+
+ public void Dispose() {
+ l = null;
+ }
+
+ private void VerifyState() {
+ if (l == null)
+ throw new ObjectDisposedException(GetType().FullName);
+ if (ver != l._version)
+ throw new InvalidOperationException(
+ "Collection was modified; enumeration operation may not execute.");
+ }
+
+ public bool MoveNext() {
+ VerifyState();
+
+ if (next < 0)
+ return false;
+
+ if (next < l.Count) {
+ current = l.Items[next++];
+ return true;
+ }
+
+ next = -1;
+ return false;
+ }
+
+ public T Current {
+ get {
+ return current;
+ }
+ }
+
+ void IEnumerator.Reset() {
+ VerifyState();
+ next = 0;
+ }
+
+ object IEnumerator.Current {
+ get {
+ VerifyState();
+ if (next <= 0)
+ throw new InvalidOperationException();
+ return current;
+ }
+ }
+ }
+ }
}
\ No newline at end of file