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