using System; using System.Collections; using System.IO; namespace AutoUpdater { [Serializable] public class DownloadURLCollection : IList, ICloneable { #region Private Fields private const int _defaultCapacity = 16; private DownloadURL[] _array = null; private int _count = 0; [NonSerialized] private int _version = 0; #endregion #region Private Constructors private enum Tag { Default } private DownloadURLCollection(Tag tag) { } #endregion #region Public Constructors #region DownloadURLCollection() public DownloadURLCollection() { this._array = new DownloadURL[_defaultCapacity]; } #endregion #region DownloadURLCollection(Int32) public DownloadURLCollection(int capacity) { if (capacity < 0) throw new ArgumentOutOfRangeException("capacity", capacity, "Argument cannot be negative."); this._array = new DownloadURL[capacity]; } #endregion #region DownloadURLCollection(DownloadURLCollection) public DownloadURLCollection(DownloadURLCollection collection) { if (collection == null) throw new ArgumentNullException("collection"); this._array = new DownloadURL[collection.Count]; AddRange(collection); } #endregion #region DownloadURLCollection(DownloadURL[]) public DownloadURLCollection(DownloadURL[] array) { if (array == null) throw new ArgumentNullException("array"); this._array = new DownloadURL[array.Length]; AddRange(array); } #endregion #endregion #region Protected Properties #region InnerArray protected virtual DownloadURL[] InnerArray { get { return this._array; } } #endregion #endregion #region Public Properties #region Capacity public virtual int Capacity { get { return this._array.Length; } set { if (value == this._array.Length) return; if (value < this._count) throw new ArgumentOutOfRangeException("Capacity", value, "Value cannot be less than Count."); if (value == 0) { this._array = new DownloadURL[_defaultCapacity]; return; } DownloadURL[] newArray = new DownloadURL[value]; Array.Copy(this._array, newArray, this._count); this._array = newArray; } } #endregion #region Count public virtual int Count { get { return this._count; } } #endregion #region IsFixedSize public virtual bool IsFixedSize { get { return false; } } #endregion #region IsReadOnly public virtual bool IsReadOnly { get { return false; } } #endregion #region IsSynchronized public virtual bool IsSynchronized { get { return false; } } #endregion #region IsUnique public virtual bool IsUnique { get { return false; } } #endregion #region Item: DownloadURL public virtual DownloadURL this[int index] { get { ValidateIndex(index); return this._array[index]; } set { ValidateIndex(index); ++this._version; this._array[index] = value; } } #endregion #region IList.Item: Object object IList.this[int index] { get { return this[index]; } set { this[index] = (DownloadURL)value; } } #endregion #region SyncRoot public virtual object SyncRoot { get { return this; } } #endregion #endregion #region Public Methods #region Add(DownloadURL) public virtual int Add(DownloadURL value) { if (this._count == this._array.Length) EnsureCapacity(this._count + 1); ++this._version; this._array[this._count] = value; return this._count++; } #endregion #region IList.Add(Object) int IList.Add(object value) { return Add((DownloadURL)value); } #endregion #region AddRange(DownloadURLCollection) public virtual void AddRange(DownloadURLCollection collection) { if (collection == null) throw new ArgumentNullException("collection"); if (collection.Count == 0) return; if (this._count + collection.Count > this._array.Length) EnsureCapacity(this._count + collection.Count); ++this._version; Array.Copy(collection.InnerArray, 0, this._array, this._count, collection.Count); this._count += collection.Count; } #endregion #region AddRange(DownloadURL[]) public virtual void AddRange(DownloadURL[] array) { if (array == null) throw new ArgumentNullException("array"); if (array.Length == 0) return; if (this._count + array.Length > this._array.Length) EnsureCapacity(this._count + array.Length); ++this._version; Array.Copy(array, 0, this._array, this._count, array.Length); this._count += array.Length; } #endregion #region BinarySearch public virtual int BinarySearch(DownloadURL value) { return Array.BinarySearch(this._array, 0, this._count, value); } #endregion #region Clear public virtual void Clear() { if (this._count == 0) return; ++this._version; Array.Clear(this._array, 0, this._count); this._count = 0; } #endregion #region Clone public virtual object Clone() { DownloadURLCollection collection = new DownloadURLCollection(this._count); Array.Copy(this._array, 0, collection._array, 0, this._count); collection._count = this._count; collection._version = this._version; return collection; } #endregion #region Contains(DownloadURL) public bool Contains(DownloadURL value) { return (IndexOf(value) >= 0); } #endregion #region IList.Contains(Object) bool IList.Contains(object value) { return Contains((DownloadURL)value); } #endregion #region CopyTo(DownloadURL[]) public virtual void CopyTo(DownloadURL[] array) { CheckTargetArray(array, 0); Array.Copy(this._array, array, this._count); } #endregion #region CopyTo(DownloadURL[], Int32) public virtual void CopyTo(DownloadURL[] array, int arrayIndex) { CheckTargetArray(array, arrayIndex); Array.Copy(this._array, 0, array, arrayIndex, this._count); } #endregion #region ICollection.CopyTo(Array, Int32) void ICollection.CopyTo(Array array, int arrayIndex) { CheckTargetArray(array, arrayIndex); CopyTo((DownloadURL[])array, arrayIndex); } #endregion #region GetEnumerator: IDownloadURLEnumerator public virtual DownloadURLCollection.Enumerator GetEnumerator() { return new Enumerator(this); } #endregion #region IEnumerable.GetEnumerator: IEnumerator IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); } #endregion #region IndexOf(DownloadURL) public virtual int IndexOf(DownloadURL value) { return Array.IndexOf(this._array, value, 0, this._count); } #endregion #region IList.IndexOf(Object) int IList.IndexOf(object value) { return IndexOf((DownloadURL)value); } #endregion #region Insert(Int32, DownloadURL) public virtual void Insert(int index, DownloadURL value) { if (index < 0) throw new ArgumentOutOfRangeException("index", index, "Argument cannot be negative."); if (index > this._count) throw new ArgumentOutOfRangeException("index", index, "Argument cannot exceed Count."); if (this._count == this._array.Length) EnsureCapacity(this._count + 1); ++this._version; if (index < this._count) Array.Copy(this._array, index, this._array, index + 1, this._count - index); this._array[index] = value; ++this._count; } #endregion #region IList.Insert(Int32, Object) void IList.Insert(int index, object value) { Insert(index, (DownloadURL)value); } #endregion #region ReadOnly public static DownloadURLCollection ReadOnly(DownloadURLCollection collection) { if (collection == null) throw new ArgumentNullException("collection"); return new ReadOnlyList(collection); } #endregion #region Remove(DownloadURL) public virtual void Remove(DownloadURL value) { int index = IndexOf(value); if (index >= 0) RemoveAt(index); } #endregion #region IList.Remove(Object) void IList.Remove(object value) { Remove((DownloadURL)value); } #endregion #region RemoveAt public virtual void RemoveAt(int index) { ValidateIndex(index); ++this._version; if (index < --this._count) Array.Copy(this._array, index + 1, this._array, index, this._count - index); this._array[this._count] = null; } #endregion #region RemoveRange public virtual void RemoveRange(int index, int count) { if (index < 0) throw new ArgumentOutOfRangeException("index", index, "Argument cannot be negative."); if (count < 0) throw new ArgumentOutOfRangeException("count", count, "Argument cannot be negative."); if (index + count > this._count) throw new ArgumentException( "Arguments denote invalid range of elements."); if (count == 0) return; ++this._version; this._count -= count; if (index < this._count) Array.Copy(this._array, index + count, this._array, index, this._count - index); Array.Clear(this._array, this._count, count); } #endregion #region Reverse() public virtual void Reverse() { if (this._count <= 1) return; ++this._version; Array.Reverse(this._array, 0, this._count); } #endregion #region Reverse(Int32, Int32) public virtual void Reverse(int index, int count) { if (index < 0) throw new ArgumentOutOfRangeException("index", index, "Argument cannot be negative."); if (count < 0) throw new ArgumentOutOfRangeException("count", count, "Argument cannot be negative."); if (index + count > this._count) throw new ArgumentException( "Arguments denote invalid range of elements."); if (count <= 1 || this._count <= 1) return; ++this._version; Array.Reverse(this._array, index, count); } #endregion #region Sort() /// /// Sorts the elements in the or a portion of it. /// /// /// Sorts the elements in the entire /// using the implementation of each element. /// /// /// The is read-only. /// Please refer to for details. public virtual void Sort() { if (this._count <= 1) return; ++this._version; Array.Sort(this._array, 0, this._count); } #endregion #region Sort(IComparer) /// /// Sorts the elements in the entire /// using the specified interface. /// /// /// The implementation to use when comparing elements. /// -or- /// A null reference to use the implementation /// of each element. /// /// The is read-only. /// Please refer to for details. public virtual void Sort(IComparer comparer) { if (this._count <= 1) return; ++this._version; Array.Sort(this._array, 0, this._count, comparer); } #endregion #region Sort(Int32, Int32, IComparer) /// /// Sorts the elements in the specified range /// using the specified interface. /// /// The zero-based starting index of the range /// of elements to sort. /// The number of elements to sort. /// /// The implementation to use when comparing elements. /// -or- /// A null reference to use the implementation /// of each element. /// /// and do not denote a /// valid range of elements in the . /// /// is less than zero. /// -or- /// is less than zero. /// /// /// The is read-only. /// Please refer to for details. public virtual void Sort(int index, int count, IComparer comparer) { if (index < 0) throw new ArgumentOutOfRangeException("index", index, "Argument cannot be negative."); if (count < 0) throw new ArgumentOutOfRangeException("count", count, "Argument cannot be negative."); if (index + count > this._count) throw new ArgumentException( "Arguments denote invalid range of elements."); if (count <= 1 || this._count <= 1) return; ++this._version; Array.Sort(this._array, index, count, comparer); } #endregion #region Synchronized /// /// Returns a synchronized (thread-safe) wrapper /// for the specified . /// /// The to synchronize. /// /// A synchronized (thread-safe) wrapper around . /// /// /// is a null reference. /// Please refer to for details. public static DownloadURLCollection Synchronized(DownloadURLCollection collection) { if (collection == null) throw new ArgumentNullException("collection"); return new SyncList(collection); } #endregion #region ToArray /// /// Copies the elements of the to a new /// of elements. /// /// A one-dimensional of /// elements containing copies of the elements of the . /// Please refer to for details. public virtual DownloadURL[] ToArray() { DownloadURL[] array = new DownloadURL[this._count]; Array.Copy(this._array, array, this._count); return array; } #endregion #region TrimToSize /// /// Sets the capacity to the actual number of elements in the . /// /// /// The is read-only. /// -or- /// The DownloadURLCollection has a fixed size. /// Please refer to for details. public virtual void TrimToSize() { Capacity = this._count; } #endregion #region Unique /// /// Returns a wrapper for the specified /// ensuring that all elements are unique. /// /// The to wrap. /// /// A wrapper around ensuring that all elements are unique. /// /// /// contains duplicate elements. /// /// is a null reference. /// /// The Unique wrapper provides a set-like collection by ensuring /// that all elements in the are unique. /// /// Unique raises an if the specified /// contains any duplicate elements. The returned /// wrapper raises a whenever the user attempts /// to add an element that is already contained in the DownloadURLCollection. /// /// Note: The Unique wrapper reflects any changes made /// to the underlying , including the possible /// creation of duplicate elements. The uniqueness of all elements is therefore /// no longer assured if the underlying collection is manipulated directly. /// public static DownloadURLCollection Unique(DownloadURLCollection collection) { if (collection == null) throw new ArgumentNullException("collection"); for (int i = collection.Count - 1; i > 0; i--) if (collection.IndexOf(collection[i]) < i) throw new ArgumentException("collection", "Argument cannot contain duplicate elements."); return new UniqueList(collection); } #endregion #endregion #region Private Methods #region CheckEnumIndex private void CheckEnumIndex(int index) { if (index < 0 || index >= this._count) throw new InvalidOperationException( "Enumerator is not on a collection element."); } #endregion #region CheckEnumVersion private void CheckEnumVersion(int version) { if (version != this._version) throw new InvalidOperationException( "Enumerator invalidated by modification to collection."); } #endregion #region CheckTargetArray private void CheckTargetArray(Array array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); if (array.Rank > 1) throw new ArgumentException( "Argument cannot be multidimensional.", "array"); if (arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, "Argument cannot be negative."); if (arrayIndex >= array.Length) throw new ArgumentException( "Argument must be less than array length.", "arrayIndex"); if (this._count > array.Length - arrayIndex) throw new ArgumentException( "Argument section must be large enough for collection.", "array"); } #endregion #region EnsureCapacity private void EnsureCapacity(int minimum) { int newCapacity = (this._array.Length == 0 ? _defaultCapacity : this._array.Length * 2); if (newCapacity < minimum) newCapacity = minimum; Capacity = newCapacity; } #endregion #region ValidateIndex private void ValidateIndex(int index) { if (index < 0) throw new ArgumentOutOfRangeException("index", index, "Argument cannot be negative."); if (index >= this._count) throw new ArgumentOutOfRangeException("index", index, "Argument must be less than Count."); } #endregion #endregion #region Class Enumerator [Serializable] public sealed class Enumerator : IEnumerator { #region Private Fields private readonly DownloadURLCollection _collection; private readonly int _version; private int _index; #endregion #region Internal Constructors internal Enumerator(DownloadURLCollection collection) { this._collection = collection; this._version = collection._version; this._index = -1; } #endregion #region Public Properties public DownloadURL Current { get { this._collection.CheckEnumIndex(this._index); this._collection.CheckEnumVersion(this._version); return this._collection[this._index]; } } object IEnumerator.Current { get { return Current; } } #endregion #region Public Methods public bool MoveNext() { this._collection.CheckEnumVersion(this._version); return (++this._index < this._collection.Count); } public void Reset() { this._collection.CheckEnumVersion(this._version); this._index = -1; } #endregion } #endregion #region Class ReadOnlyList [Serializable] private sealed class ReadOnlyList : DownloadURLCollection { #region Private Fields private DownloadURLCollection _collection; #endregion #region Internal Constructors internal ReadOnlyList(DownloadURLCollection collection) : base(Tag.Default) { this._collection = collection; } #endregion #region Protected Properties protected override DownloadURL[] InnerArray { get { return this._collection.InnerArray; } } #endregion #region Public Properties public override int Capacity { get { return this._collection.Capacity; } set { throw new NotSupportedException( "Read-only collections cannot be modified."); } } public override int Count { get { return this._collection.Count; } } public override bool IsFixedSize { get { return true; } } public override bool IsReadOnly { get { return true; } } public override bool IsSynchronized { get { return this._collection.IsSynchronized; } } public override bool IsUnique { get { return this._collection.IsUnique; } } public override DownloadURL this[int index] { get { return this._collection[index]; } set { throw new NotSupportedException( "Read-only collections cannot be modified."); } } public override object SyncRoot { get { return this._collection.SyncRoot; } } #endregion #region Public Methods public override int Add(DownloadURL value) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void AddRange(DownloadURLCollection collection) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void AddRange(DownloadURL[] array) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override int BinarySearch(DownloadURL value) { return this._collection.BinarySearch(value); } public override void Clear() { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override object Clone() { return new ReadOnlyList((DownloadURLCollection)this._collection.Clone()); } public override void CopyTo(DownloadURL[] array) { this._collection.CopyTo(array); } public override void CopyTo(DownloadURL[] array, int arrayIndex) { this._collection.CopyTo(array, arrayIndex); } public override DownloadURLCollection.Enumerator GetEnumerator() { return this._collection.GetEnumerator(); } public override int IndexOf(DownloadURL value) { return this._collection.IndexOf(value); } public override void Insert(int index, DownloadURL value) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void Remove(DownloadURL value) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void RemoveAt(int index) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void RemoveRange(int index, int count) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void Reverse() { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void Reverse(int index, int count) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void Sort() { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void Sort(IComparer comparer) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override void Sort(int index, int count, IComparer comparer) { throw new NotSupportedException( "Read-only collections cannot be modified."); } public override DownloadURL[] ToArray() { return this._collection.ToArray(); } public override void TrimToSize() { throw new NotSupportedException( "Read-only collections cannot be modified."); } #endregion } #endregion #region Class SyncList [Serializable] private sealed class SyncList : DownloadURLCollection { #region Private Fields private DownloadURLCollection _collection; private object _root; #endregion #region Internal Constructors internal SyncList(DownloadURLCollection collection) : base(Tag.Default) { this._root = collection.SyncRoot; this._collection = collection; } #endregion #region Protected Properties protected override DownloadURL[] InnerArray { get { lock (this._root) return this._collection.InnerArray; } } #endregion #region Public Properties public override int Capacity { get { lock (this._root) return this._collection.Capacity; } set { lock (this._root) this._collection.Capacity = value; } } public override int Count { get { lock (this._root) return this._collection.Count; } } public override bool IsFixedSize { get { return this._collection.IsFixedSize; } } public override bool IsReadOnly { get { return this._collection.IsReadOnly; } } public override bool IsSynchronized { get { return true; } } public override bool IsUnique { get { return this._collection.IsUnique; } } public override DownloadURL this[int index] { get { lock (this._root) return this._collection[index]; } set { lock (this._root) this._collection[index] = value; } } public override object SyncRoot { get { return this._root; } } #endregion #region Public Methods public override int Add(DownloadURL value) { lock (this._root) return this._collection.Add(value); } public override void AddRange(DownloadURLCollection collection) { lock (this._root) this._collection.AddRange(collection); } public override void AddRange(DownloadURL[] array) { lock (this._root) this._collection.AddRange(array); } public override int BinarySearch(DownloadURL value) { lock (this._root) return this._collection.BinarySearch(value); } public override void Clear() { lock (this._root) this._collection.Clear(); } public override object Clone() { lock (this._root) return new SyncList((DownloadURLCollection)this._collection.Clone()); } public override void CopyTo(DownloadURL[] array) { lock (this._root) this._collection.CopyTo(array); } public override void CopyTo(DownloadURL[] array, int arrayIndex) { lock (this._root) this._collection.CopyTo(array, arrayIndex); } public override DownloadURLCollection.Enumerator GetEnumerator() { lock (this._root) return this._collection.GetEnumerator(); } public override int IndexOf(DownloadURL value) { lock (this._root) return this._collection.IndexOf(value); } public override void Insert(int index, DownloadURL value) { lock (this._root) this._collection.Insert(index, value); } public override void Remove(DownloadURL value) { lock (this._root) this._collection.Remove(value); } public override void RemoveAt(int index) { lock (this._root) this._collection.RemoveAt(index); } public override void RemoveRange(int index, int count) { lock (this._root) this._collection.RemoveRange(index, count); } public override void Reverse() { lock (this._root) this._collection.Reverse(); } public override void Reverse(int index, int count) { lock (this._root) this._collection.Reverse(index, count); } public override void Sort() { lock (this._root) this._collection.Sort(); } public override void Sort(IComparer comparer) { lock (this._root) this._collection.Sort(comparer); } public override void Sort(int index, int count, IComparer comparer) { lock (this._root) this._collection.Sort(index, count, comparer); } public override DownloadURL[] ToArray() { lock (this._root) return this._collection.ToArray(); } public override void TrimToSize() { lock (this._root) this._collection.TrimToSize(); } #endregion } #endregion #region Class UniqueList [Serializable] private sealed class UniqueList : DownloadURLCollection { #region Private Fields private DownloadURLCollection _collection; #endregion #region Internal Constructors internal UniqueList(DownloadURLCollection collection) : base(Tag.Default) { this._collection = collection; } #endregion #region Protected Properties protected override DownloadURL[] InnerArray { get { return this._collection.InnerArray; } } #endregion #region Public Properties public override int Capacity { get { return this._collection.Capacity; } set { this._collection.Capacity = value; } } public override int Count { get { return this._collection.Count; } } public override bool IsFixedSize { get { return this._collection.IsFixedSize; } } public override bool IsReadOnly { get { return this._collection.IsReadOnly; } } public override bool IsSynchronized { get { return this._collection.IsSynchronized; } } public override bool IsUnique { get { return true; } } public override DownloadURL this[int index] { get { return this._collection[index]; } set { CheckUnique(index, value); this._collection[index] = value; } } public override object SyncRoot { get { return this._collection.SyncRoot; } } #endregion #region Public Methods public override int Add(DownloadURL value) { CheckUnique(value); return this._collection.Add(value); } public override void AddRange(DownloadURLCollection collection) { foreach (DownloadURL value in collection) CheckUnique(value); this._collection.AddRange(collection); } public override void AddRange(DownloadURL[] array) { foreach (DownloadURL value in array) CheckUnique(value); this._collection.AddRange(array); } public override int BinarySearch(DownloadURL value) { return this._collection.BinarySearch(value); } public override void Clear() { this._collection.Clear(); } public override object Clone() { return new UniqueList((DownloadURLCollection)this._collection.Clone()); } public override void CopyTo(DownloadURL[] array) { this._collection.CopyTo(array); } public override void CopyTo(DownloadURL[] array, int arrayIndex) { this._collection.CopyTo(array, arrayIndex); } public override DownloadURLCollection.Enumerator GetEnumerator() { return this._collection.GetEnumerator(); } public override int IndexOf(DownloadURL value) { return this._collection.IndexOf(value); } public override void Insert(int index, DownloadURL value) { CheckUnique(value); this._collection.Insert(index, value); } public override void Remove(DownloadURL value) { this._collection.Remove(value); } public override void RemoveAt(int index) { this._collection.RemoveAt(index); } public override void RemoveRange(int index, int count) { this._collection.RemoveRange(index, count); } public override void Reverse() { this._collection.Reverse(); } public override void Reverse(int index, int count) { this._collection.Reverse(index, count); } public override void Sort() { this._collection.Sort(); } public override void Sort(IComparer comparer) { this._collection.Sort(comparer); } public override void Sort(int index, int count, IComparer comparer) { this._collection.Sort(index, count, comparer); } public override DownloadURL[] ToArray() { return this._collection.ToArray(); } public override void TrimToSize() { this._collection.TrimToSize(); } #endregion #region Private Methods private void CheckUnique(DownloadURL value) { if (IndexOf(value) >= 0) throw new NotSupportedException( "Unique collections cannot contain duplicate elements."); } private void CheckUnique(int index, DownloadURL value) { int existing = IndexOf(value); if (existing >= 0 && existing != index) throw new NotSupportedException( "Unique collections cannot contain duplicate elements."); } #endregion } #endregion } }