PageRenderTime 25ms CodeModel.GetById 8ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Mono.Collections.Generic/Collection.cs

http://github.com/jbevain/cecil
C# | 418 lines | 315 code | 94 blank | 9 comment | 34 complexity | bd6b47aeb5287076339069a0364d6a6b MD5 | raw file
  1//
  2// Author:
  3//   Jb Evain (jbevain@gmail.com)
  4//
  5// Copyright (c) 2008 - 2015 Jb Evain
  6// Copyright (c) 2008 - 2011 Novell, Inc.
  7//
  8// Licensed under the MIT/X11 license.
  9//
 10
 11using System;
 12using System.Collections;
 13using System.Collections.Generic;
 14
 15using Mono.Cecil;
 16
 17namespace Mono.Collections.Generic {
 18
 19	public class Collection<T> : IList<T>, IList {
 20
 21		internal T [] items;
 22		internal int size;
 23		int version;
 24
 25		public int Count {
 26			get { return size; }
 27		}
 28
 29		public T this [int index] {
 30			get {
 31				if (index >= size)
 32					throw new ArgumentOutOfRangeException ();
 33
 34				return items [index];
 35			}
 36			set {
 37				CheckIndex (index);
 38				if (index == size)
 39					throw new ArgumentOutOfRangeException ();
 40
 41				OnSet (value, index);
 42
 43				items [index] = value;
 44			}
 45		}
 46
 47		public int Capacity {
 48			get { return items.Length; }
 49			set {
 50				if (value < 0 || value < size)
 51					throw new ArgumentOutOfRangeException ();
 52
 53				Resize (value);
 54			}
 55		}
 56
 57		bool ICollection<T>.IsReadOnly {
 58			get { return false; }
 59		}
 60
 61		bool IList.IsFixedSize {
 62			get { return false; }
 63		}
 64
 65		bool IList.IsReadOnly {
 66			get { return false; }
 67		}
 68
 69		object IList.this [int index] {
 70			get { return this [index]; }
 71			set {
 72				CheckIndex (index);
 73
 74				try {
 75					this [index] = (T) value;
 76					return;
 77				} catch (InvalidCastException) {
 78				} catch (NullReferenceException) {
 79				}
 80
 81				throw new ArgumentException ();
 82			}
 83		}
 84
 85		int ICollection.Count {
 86			get { return Count; }
 87		}
 88
 89		bool ICollection.IsSynchronized {
 90			get { return false; }
 91		}
 92
 93		object ICollection.SyncRoot {
 94			get { return this; }
 95		}
 96
 97		public Collection ()
 98		{
 99			items = Empty<T>.Array;
100		}
101
102		public Collection (int capacity)
103		{
104			if (capacity < 0)
105				throw new ArgumentOutOfRangeException ();
106
107			items = capacity == 0 
108				? Empty<T>.Array
109				: new T [capacity];
110		}
111
112		public Collection (ICollection<T> items)
113		{
114			if (items == null)
115				throw new ArgumentNullException ("items");
116
117			this.items = new T [items.Count];
118			items.CopyTo (this.items, 0);
119			this.size = this.items.Length;
120		}
121
122		public void Add (T item)
123		{
124			if (size == items.Length)
125				Grow (1);
126
127			OnAdd (item, size);
128
129			items [size++] = item;
130			version++;
131		}
132
133		public bool Contains (T item)
134		{
135			return IndexOf (item) != -1;
136		}
137
138		public int IndexOf (T item)
139		{
140			return Array.IndexOf (items, item, 0, size);
141		}
142
143		public void Insert (int index, T item)
144		{
145			CheckIndex (index);
146			if (size == items.Length)
147				Grow (1);
148
149			OnInsert (item, index);
150
151			Shift (index, 1);
152			items [index] = item;
153			version++;
154		}
155
156		public void RemoveAt (int index)
157		{
158			if (index < 0 || index >= size)
159				throw new ArgumentOutOfRangeException ();
160
161			var item = items [index];
162
163			OnRemove (item, index);
164
165			Shift (index, -1);
166			version++;
167		}
168
169		public bool Remove (T item)
170		{
171			var index = IndexOf (item);
172			if (index == -1)
173				return false;
174
175			OnRemove (item, index);
176
177			Shift (index, -1);
178			version++;
179
180			return true;
181		}
182
183		public void Clear ()
184		{
185			OnClear ();
186
187			Array.Clear (items, 0, size);
188			size = 0;
189			version++;
190		}
191
192		public void CopyTo (T [] array, int arrayIndex)
193		{
194			Array.Copy (items, 0, array, arrayIndex, size);
195		}
196
197		public T [] ToArray ()
198		{
199			var array = new T [size];
200			Array.Copy (items, 0, array, 0, size);
201			return array;
202		}
203
204		void CheckIndex (int index)
205		{
206			if (index < 0 || index > size)
207				throw new ArgumentOutOfRangeException ();
208		}
209
210		void Shift (int start, int delta)
211		{
212			if (delta < 0)
213				start -= delta;
214
215			if (start < size)
216				Array.Copy (items, start, items, start + delta, size - start);
217
218			size += delta;
219
220			if (delta < 0)
221				Array.Clear (items, size, -delta);
222		}
223
224		protected virtual void OnAdd (T item, int index)
225		{
226		}
227
228		protected virtual void OnInsert (T item, int index)
229		{
230		}
231
232		protected virtual void OnSet (T item, int index)
233		{
234		}
235
236		protected virtual void OnRemove (T item, int index)
237		{
238		}
239
240		protected virtual void OnClear ()
241		{
242		}
243
244		internal virtual void Grow (int desired)
245		{
246			int new_size = size + desired;
247			if (new_size <= items.Length)
248				return;
249
250			const int default_capacity = 4;
251
252			new_size = System.Math.Max (
253				System.Math.Max (items.Length * 2, default_capacity),
254				new_size);
255
256			Resize (new_size);
257		}
258
259		protected void Resize (int new_size)
260		{
261			if (new_size == size)
262				return;
263			if (new_size < size)
264				throw new ArgumentOutOfRangeException ();
265
266			items = items.Resize (new_size);
267		}
268
269		int IList.Add (object value)
270		{
271			try {
272				Add ((T) value);
273				return size - 1;
274			} catch (InvalidCastException) {
275			} catch (NullReferenceException) {
276			}
277
278			throw new ArgumentException ();
279		}
280
281		void IList.Clear ()
282		{
283			Clear ();
284		}
285
286		bool IList.Contains (object value)
287		{
288			return ((IList) this).IndexOf (value) > -1;
289		}
290
291		int IList.IndexOf (object value)
292		{
293			try {
294				return IndexOf ((T) value);
295			} catch (InvalidCastException) {
296			} catch (NullReferenceException) {
297			}
298
299			return -1;
300		}
301
302		void IList.Insert (int index, object value)
303		{
304			CheckIndex (index);
305
306			try {
307				Insert (index, (T) value);
308				return;
309			} catch (InvalidCastException) {
310			} catch (NullReferenceException) {
311			}
312
313			throw new ArgumentException ();
314		}
315
316		void IList.Remove (object value)
317		{
318			try {
319				Remove ((T) value);
320			} catch (InvalidCastException) {
321			} catch (NullReferenceException) {
322			}
323		}
324
325		void IList.RemoveAt (int index)
326		{
327			RemoveAt (index);
328		}
329
330		void ICollection.CopyTo (Array array, int index)
331		{
332			Array.Copy (items, 0, array, index, size);
333		}
334
335		public Enumerator GetEnumerator ()
336		{
337			return new Enumerator (this);
338		}
339
340		IEnumerator IEnumerable.GetEnumerator ()
341		{
342			return new Enumerator (this);
343		}
344
345		IEnumerator<T> IEnumerable<T>.GetEnumerator ()
346		{
347			return new Enumerator (this);
348		}
349
350		public struct Enumerator : IEnumerator<T>, IDisposable {
351
352			Collection<T> collection;
353			T current;
354
355			int next;
356			readonly int version;
357
358			public T Current {
359				get { return current; }
360			}
361
362			object IEnumerator.Current {
363				get {
364					CheckState ();
365
366					if (next <= 0)
367						throw new InvalidOperationException ();
368
369					return current;
370				}
371			}
372
373			internal Enumerator (Collection<T> collection)
374				: this ()
375			{
376				this.collection = collection;
377				this.version = collection.version;
378			}
379
380			public bool MoveNext ()
381			{
382				CheckState ();
383
384				if (next < 0)
385					return false;
386
387				if (next < collection.size) {
388					current = collection.items [next++];
389					return true;
390				}
391
392				next = -1;
393				return false;
394			}
395
396			public void Reset ()
397			{
398				CheckState ();
399
400				next = 0;
401			}
402
403			void CheckState ()
404			{
405				if (collection == null)
406					throw new ObjectDisposedException (GetType ().FullName);
407
408				if (version != collection.version)
409					throw new InvalidOperationException ();
410			}
411
412			public void Dispose ()
413			{
414				collection = null;
415			}
416		}
417	}
418}