forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			428 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			428 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
//
 | 
						|
// Author:
 | 
						|
//   Jb Evain (jbevain@gmail.com)
 | 
						|
//
 | 
						|
// Copyright (c) 2008 - 2015 Jb Evain
 | 
						|
// Copyright (c) 2008 - 2011 Novell, Inc.
 | 
						|
//
 | 
						|
// Licensed under the MIT/X11 license.
 | 
						|
//
 | 
						|
 | 
						|
using MonoFN.Cecil;
 | 
						|
using System;
 | 
						|
using System.Collections;
 | 
						|
using System.Collections.Generic;
 | 
						|
 | 
						|
namespace MonoFN.Collections.Generic {
 | 
						|
 | 
						|
	public class Collection<T> : IList<T>, IList {
 | 
						|
 | 
						|
		internal T [] items;
 | 
						|
		internal int size;
 | 
						|
		int version;
 | 
						|
 | 
						|
		public int Count {
 | 
						|
			get { return size; }
 | 
						|
		}
 | 
						|
 | 
						|
		public T this [int index] {
 | 
						|
			get {
 | 
						|
				if (index >= size)
 | 
						|
					throw new ArgumentOutOfRangeException ();
 | 
						|
 | 
						|
				return items [index];
 | 
						|
			}
 | 
						|
			set {
 | 
						|
				CheckIndex (index);
 | 
						|
				if (index == size)
 | 
						|
					throw new ArgumentOutOfRangeException ();
 | 
						|
 | 
						|
				OnSet (value, index);
 | 
						|
 | 
						|
				items [index] = value;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public int Capacity {
 | 
						|
			get { return items.Length; }
 | 
						|
			set {
 | 
						|
				if (value < 0 || value < size)
 | 
						|
					throw new ArgumentOutOfRangeException ();
 | 
						|
 | 
						|
				Resize (value);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		bool ICollection<T>.IsReadOnly {
 | 
						|
			get { return false; }
 | 
						|
		}
 | 
						|
 | 
						|
		bool IList.IsFixedSize {
 | 
						|
			get { return false; }
 | 
						|
		}
 | 
						|
 | 
						|
		bool IList.IsReadOnly {
 | 
						|
			get { return false; }
 | 
						|
		}
 | 
						|
 | 
						|
		object IList.this [int index] {
 | 
						|
			get { return this [index]; }
 | 
						|
			set {
 | 
						|
				CheckIndex (index);
 | 
						|
 | 
						|
				try {
 | 
						|
					this [index] = (T)value;
 | 
						|
					return;
 | 
						|
				}
 | 
						|
				catch (InvalidCastException) {
 | 
						|
				}
 | 
						|
				catch (NullReferenceException) {
 | 
						|
				}
 | 
						|
 | 
						|
				throw new ArgumentException ();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		int ICollection.Count {
 | 
						|
			get { return Count; }
 | 
						|
		}
 | 
						|
 | 
						|
		bool ICollection.IsSynchronized {
 | 
						|
			get { return false; }
 | 
						|
		}
 | 
						|
 | 
						|
		object ICollection.SyncRoot {
 | 
						|
			get { return this; }
 | 
						|
		}
 | 
						|
 | 
						|
		public Collection ()
 | 
						|
		{
 | 
						|
			items = Empty<T>.Array;
 | 
						|
		}
 | 
						|
 | 
						|
		public Collection (int capacity)
 | 
						|
		{
 | 
						|
			if (capacity < 0)
 | 
						|
				throw new ArgumentOutOfRangeException ();
 | 
						|
 | 
						|
			items = capacity == 0
 | 
						|
				? Empty<T>.Array
 | 
						|
				: new T [capacity];
 | 
						|
		}
 | 
						|
 | 
						|
		public Collection (ICollection<T> items)
 | 
						|
		{
 | 
						|
			if (items == null)
 | 
						|
				throw new ArgumentNullException ("items");
 | 
						|
 | 
						|
			this.items = new T [items.Count];
 | 
						|
			items.CopyTo (this.items, 0);
 | 
						|
			this.size = this.items.Length;
 | 
						|
		}
 | 
						|
 | 
						|
		public void Add (T item)
 | 
						|
		{
 | 
						|
			if (size == items.Length)
 | 
						|
				Grow (1);
 | 
						|
 | 
						|
			OnAdd (item, size);
 | 
						|
 | 
						|
			items [size++] = item;
 | 
						|
			version++;
 | 
						|
		}
 | 
						|
 | 
						|
		public bool Contains (T item)
 | 
						|
		{
 | 
						|
			return IndexOf (item) != -1;
 | 
						|
		}
 | 
						|
 | 
						|
		public int IndexOf (T item)
 | 
						|
		{
 | 
						|
			return Array.IndexOf (items, item, 0, size);
 | 
						|
		}
 | 
						|
 | 
						|
		public void Insert (int index, T item)
 | 
						|
		{
 | 
						|
			CheckIndex (index);
 | 
						|
			if (size == items.Length)
 | 
						|
				Grow (1);
 | 
						|
 | 
						|
			OnInsert (item, index);
 | 
						|
 | 
						|
			Shift (index, 1);
 | 
						|
			items [index] = item;
 | 
						|
			version++;
 | 
						|
		}
 | 
						|
 | 
						|
		public void RemoveAt (int index)
 | 
						|
		{
 | 
						|
			if (index < 0 || index >= size)
 | 
						|
				throw new ArgumentOutOfRangeException ();
 | 
						|
 | 
						|
			var item = items [index];
 | 
						|
 | 
						|
			OnRemove (item, index);
 | 
						|
 | 
						|
			Shift (index, -1);
 | 
						|
			version++;
 | 
						|
		}
 | 
						|
 | 
						|
		public bool Remove (T item)
 | 
						|
		{
 | 
						|
			var index = IndexOf (item);
 | 
						|
			if (index == -1)
 | 
						|
				return false;
 | 
						|
 | 
						|
			OnRemove (item, index);
 | 
						|
 | 
						|
			Shift (index, -1);
 | 
						|
			version++;
 | 
						|
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		public void Clear ()
 | 
						|
		{
 | 
						|
			OnClear ();
 | 
						|
 | 
						|
			Array.Clear (items, 0, size);
 | 
						|
			size = 0;
 | 
						|
			version++;
 | 
						|
		}
 | 
						|
 | 
						|
		public void CopyTo (T [] array, int arrayIndex)
 | 
						|
		{
 | 
						|
			Array.Copy (items, 0, array, arrayIndex, size);
 | 
						|
		}
 | 
						|
 | 
						|
		public T [] ToArray ()
 | 
						|
		{
 | 
						|
			var array = new T [size];
 | 
						|
			Array.Copy (items, 0, array, 0, size);
 | 
						|
			return array;
 | 
						|
		}
 | 
						|
 | 
						|
		void CheckIndex (int index)
 | 
						|
		{
 | 
						|
			if (index < 0 || index > size)
 | 
						|
				throw new ArgumentOutOfRangeException ();
 | 
						|
		}
 | 
						|
 | 
						|
		void Shift (int start, int delta)
 | 
						|
		{
 | 
						|
			if (delta < 0)
 | 
						|
				start -= delta;
 | 
						|
 | 
						|
			if (start < size)
 | 
						|
				Array.Copy (items, start, items, start + delta, size - start);
 | 
						|
 | 
						|
			size += delta;
 | 
						|
 | 
						|
			if (delta < 0)
 | 
						|
				Array.Clear (items, size, -delta);
 | 
						|
		}
 | 
						|
 | 
						|
		protected virtual void OnAdd (T item, int index)
 | 
						|
		{
 | 
						|
		}
 | 
						|
 | 
						|
		protected virtual void OnInsert (T item, int index)
 | 
						|
		{
 | 
						|
		}
 | 
						|
 | 
						|
		protected virtual void OnSet (T item, int index)
 | 
						|
		{
 | 
						|
		}
 | 
						|
 | 
						|
		protected virtual void OnRemove (T item, int index)
 | 
						|
		{
 | 
						|
		}
 | 
						|
 | 
						|
		protected virtual void OnClear ()
 | 
						|
		{
 | 
						|
		}
 | 
						|
 | 
						|
		internal virtual void Grow (int desired)
 | 
						|
		{
 | 
						|
			int new_size = size + desired;
 | 
						|
			if (new_size <= items.Length)
 | 
						|
				return;
 | 
						|
 | 
						|
			const int default_capacity = 4;
 | 
						|
 | 
						|
			new_size = System.Math.Max (
 | 
						|
				System.Math.Max (items.Length * 2, default_capacity),
 | 
						|
				new_size);
 | 
						|
 | 
						|
			Resize (new_size);
 | 
						|
		}
 | 
						|
 | 
						|
		protected void Resize (int new_size)
 | 
						|
		{
 | 
						|
			if (new_size == size)
 | 
						|
				return;
 | 
						|
			if (new_size < size)
 | 
						|
				throw new ArgumentOutOfRangeException ();
 | 
						|
 | 
						|
			items = items.Resize (new_size);
 | 
						|
		}
 | 
						|
 | 
						|
		int IList.Add (object value)
 | 
						|
		{
 | 
						|
			try {
 | 
						|
				Add ((T)value);
 | 
						|
				return size - 1;
 | 
						|
			}
 | 
						|
			catch (InvalidCastException) {
 | 
						|
			}
 | 
						|
			catch (NullReferenceException) {
 | 
						|
			}
 | 
						|
 | 
						|
			throw new ArgumentException ();
 | 
						|
		}
 | 
						|
 | 
						|
		void IList.Clear ()
 | 
						|
		{
 | 
						|
			Clear ();
 | 
						|
		}
 | 
						|
 | 
						|
		bool IList.Contains (object value)
 | 
						|
		{
 | 
						|
			return ((IList)this).IndexOf (value) > -1;
 | 
						|
		}
 | 
						|
 | 
						|
		int IList.IndexOf (object value)
 | 
						|
		{
 | 
						|
			try {
 | 
						|
				return IndexOf ((T)value);
 | 
						|
			}
 | 
						|
			catch (InvalidCastException) {
 | 
						|
			}
 | 
						|
			catch (NullReferenceException) {
 | 
						|
			}
 | 
						|
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		void IList.Insert (int index, object value)
 | 
						|
		{
 | 
						|
			CheckIndex (index);
 | 
						|
 | 
						|
			try {
 | 
						|
				Insert (index, (T)value);
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			catch (InvalidCastException) {
 | 
						|
			}
 | 
						|
			catch (NullReferenceException) {
 | 
						|
			}
 | 
						|
 | 
						|
			throw new ArgumentException ();
 | 
						|
		}
 | 
						|
 | 
						|
		void IList.Remove (object value)
 | 
						|
		{
 | 
						|
			try {
 | 
						|
				Remove ((T)value);
 | 
						|
			}
 | 
						|
			catch (InvalidCastException) {
 | 
						|
			}
 | 
						|
			catch (NullReferenceException) {
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		void IList.RemoveAt (int index)
 | 
						|
		{
 | 
						|
			RemoveAt (index);
 | 
						|
		}
 | 
						|
 | 
						|
		void ICollection.CopyTo (Array array, int index)
 | 
						|
		{
 | 
						|
			Array.Copy (items, 0, array, index, size);
 | 
						|
		}
 | 
						|
 | 
						|
		public Enumerator GetEnumerator ()
 | 
						|
		{
 | 
						|
			return new Enumerator (this);
 | 
						|
		}
 | 
						|
 | 
						|
		IEnumerator IEnumerable.GetEnumerator ()
 | 
						|
		{
 | 
						|
			return new Enumerator (this);
 | 
						|
		}
 | 
						|
 | 
						|
		IEnumerator<T> IEnumerable<T>.GetEnumerator ()
 | 
						|
		{
 | 
						|
			return new Enumerator (this);
 | 
						|
		}
 | 
						|
 | 
						|
		public struct Enumerator : IEnumerator<T>, IDisposable {
 | 
						|
 | 
						|
			Collection<T> collection;
 | 
						|
			T current;
 | 
						|
 | 
						|
			int next;
 | 
						|
			readonly int version;
 | 
						|
 | 
						|
			public T Current {
 | 
						|
				get { return current; }
 | 
						|
			}
 | 
						|
 | 
						|
			object IEnumerator.Current {
 | 
						|
				get {
 | 
						|
					CheckState ();
 | 
						|
 | 
						|
					if (next <= 0)
 | 
						|
						throw new InvalidOperationException ();
 | 
						|
 | 
						|
					return current;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			internal Enumerator (Collection<T> collection)
 | 
						|
				: this ()
 | 
						|
			{
 | 
						|
				this.collection = collection;
 | 
						|
				this.version = collection.version;
 | 
						|
			}
 | 
						|
 | 
						|
			public bool MoveNext ()
 | 
						|
			{
 | 
						|
				CheckState ();
 | 
						|
 | 
						|
				if (next < 0)
 | 
						|
					return false;
 | 
						|
 | 
						|
				if (next < collection.size) {
 | 
						|
					current = collection.items [next++];
 | 
						|
					return true;
 | 
						|
				}
 | 
						|
 | 
						|
				next = -1;
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			public void Reset ()
 | 
						|
			{
 | 
						|
				CheckState ();
 | 
						|
 | 
						|
				next = 0;
 | 
						|
			}
 | 
						|
 | 
						|
			void CheckState ()
 | 
						|
			{
 | 
						|
				if (collection == null)
 | 
						|
					throw new ObjectDisposedException (GetType ().FullName);
 | 
						|
 | 
						|
				if (version != collection.version)
 | 
						|
					throw new InvalidOperationException ();
 | 
						|
			}
 | 
						|
 | 
						|
			public void Dispose ()
 | 
						|
			{
 | 
						|
				collection = null;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |