/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. using System;
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using Mono.Cecil;
  14. namespace Mono.Collections.Generic {
  15. public class Collection<T> : IList<T>, IList {
  16. internal T [] items;
  17. internal int size;
  18. int version;
  19. public int Count {
  20. get { return size; }
  21. }
  22. public T this [int index] {
  23. get {
  24. if (index >= size)
  25. throw new ArgumentOutOfRangeException ();
  26. return items [index];
  27. }
  28. set {
  29. CheckIndex (index);
  30. if (index == size)
  31. throw new ArgumentOutOfRangeException ();
  32. OnSet (value, index);
  33. items [index] = value;
  34. }
  35. }
  36. public int Capacity {
  37. get { return items.Length; }
  38. set {
  39. if (value < 0 || value < size)
  40. throw new ArgumentOutOfRangeException ();
  41. Resize (value);
  42. }
  43. }
  44. bool ICollection<T>.IsReadOnly {
  45. get { return false; }
  46. }
  47. bool IList.IsFixedSize {
  48. get { return false; }
  49. }
  50. bool IList.IsReadOnly {
  51. get { return false; }
  52. }
  53. object IList.this [int index] {
  54. get { return this [index]; }
  55. set {
  56. CheckIndex (index);
  57. try {
  58. this [index] = (T) value;
  59. return;
  60. } catch (InvalidCastException) {
  61. } catch (NullReferenceException) {
  62. }
  63. throw new ArgumentException ();
  64. }
  65. }
  66. int ICollection.Count {
  67. get { return Count; }
  68. }
  69. bool ICollection.IsSynchronized {
  70. get { return false; }
  71. }
  72. object ICollection.SyncRoot {
  73. get { return this; }
  74. }
  75. public Collection ()
  76. {
  77. items = Empty<T>.Array;
  78. }
  79. public Collection (int capacity)
  80. {
  81. if (capacity < 0)
  82. throw new ArgumentOutOfRangeException ();
  83. items = capacity == 0
  84. ? Empty<T>.Array
  85. : new T [capacity];
  86. }
  87. public Collection (ICollection<T> items)
  88. {
  89. if (items == null)
  90. throw new ArgumentNullException ("items");
  91. this.items = new T [items.Count];
  92. items.CopyTo (this.items, 0);
  93. this.size = this.items.Length;
  94. }
  95. public void Add (T item)
  96. {
  97. if (size == items.Length)
  98. Grow (1);
  99. OnAdd (item, size);
  100. items [size++] = item;
  101. version++;
  102. }
  103. public bool Contains (T item)
  104. {
  105. return IndexOf (item) != -1;
  106. }
  107. public int IndexOf (T item)
  108. {
  109. return Array.IndexOf (items, item, 0, size);
  110. }
  111. public void Insert (int index, T item)
  112. {
  113. CheckIndex (index);
  114. if (size == items.Length)
  115. Grow (1);
  116. OnInsert (item, index);
  117. Shift (index, 1);
  118. items [index] = item;
  119. version++;
  120. }
  121. public void RemoveAt (int index)
  122. {
  123. if (index < 0 || index >= size)
  124. throw new ArgumentOutOfRangeException ();
  125. var item = items [index];
  126. OnRemove (item, index);
  127. Shift (index, -1);
  128. version++;
  129. }
  130. public bool Remove (T item)
  131. {
  132. var index = IndexOf (item);
  133. if (index == -1)
  134. return false;
  135. OnRemove (item, index);
  136. Shift (index, -1);
  137. version++;
  138. return true;
  139. }
  140. public void Clear ()
  141. {
  142. OnClear ();
  143. Array.Clear (items, 0, size);
  144. size = 0;
  145. version++;
  146. }
  147. public void CopyTo (T [] array, int arrayIndex)
  148. {
  149. Array.Copy (items, 0, array, arrayIndex, size);
  150. }
  151. public T [] ToArray ()
  152. {
  153. var array = new T [size];
  154. Array.Copy (items, 0, array, 0, size);
  155. return array;
  156. }
  157. void CheckIndex (int index)
  158. {
  159. if (index < 0 || index > size)
  160. throw new ArgumentOutOfRangeException ();
  161. }
  162. void Shift (int start, int delta)
  163. {
  164. if (delta < 0)
  165. start -= delta;
  166. if (start < size)
  167. Array.Copy (items, start, items, start + delta, size - start);
  168. size += delta;
  169. if (delta < 0)
  170. Array.Clear (items, size, -delta);
  171. }
  172. protected virtual void OnAdd (T item, int index)
  173. {
  174. }
  175. protected virtual void OnInsert (T item, int index)
  176. {
  177. }
  178. protected virtual void OnSet (T item, int index)
  179. {
  180. }
  181. protected virtual void OnRemove (T item, int index)
  182. {
  183. }
  184. protected virtual void OnClear ()
  185. {
  186. }
  187. internal virtual void Grow (int desired)
  188. {
  189. int new_size = size + desired;
  190. if (new_size <= items.Length)
  191. return;
  192. const int default_capacity = 4;
  193. new_size = System.Math.Max (
  194. System.Math.Max (items.Length * 2, default_capacity),
  195. new_size);
  196. Resize (new_size);
  197. }
  198. protected void Resize (int new_size)
  199. {
  200. if (new_size == size)
  201. return;
  202. if (new_size < size)
  203. throw new ArgumentOutOfRangeException ();
  204. items = items.Resize (new_size);
  205. }
  206. int IList.Add (object value)
  207. {
  208. try {
  209. Add ((T) value);
  210. return size - 1;
  211. } catch (InvalidCastException) {
  212. } catch (NullReferenceException) {
  213. }
  214. throw new ArgumentException ();
  215. }
  216. void IList.Clear ()
  217. {
  218. Clear ();
  219. }
  220. bool IList.Contains (object value)
  221. {
  222. return ((IList) this).IndexOf (value) > -1;
  223. }
  224. int IList.IndexOf (object value)
  225. {
  226. try {
  227. return IndexOf ((T) value);
  228. } catch (InvalidCastException) {
  229. } catch (NullReferenceException) {
  230. }
  231. return -1;
  232. }
  233. void IList.Insert (int index, object value)
  234. {
  235. CheckIndex (index);
  236. try {
  237. Insert (index, (T) value);
  238. return;
  239. } catch (InvalidCastException) {
  240. } catch (NullReferenceException) {
  241. }
  242. throw new ArgumentException ();
  243. }
  244. void IList.Remove (object value)
  245. {
  246. try {
  247. Remove ((T) value);
  248. } catch (InvalidCastException) {
  249. } catch (NullReferenceException) {
  250. }
  251. }
  252. void IList.RemoveAt (int index)
  253. {
  254. RemoveAt (index);
  255. }
  256. void ICollection.CopyTo (Array array, int index)
  257. {
  258. Array.Copy (items, 0, array, index, size);
  259. }
  260. public Enumerator GetEnumerator ()
  261. {
  262. return new Enumerator (this);
  263. }
  264. IEnumerator IEnumerable.GetEnumerator ()
  265. {
  266. return new Enumerator (this);
  267. }
  268. IEnumerator<T> IEnumerable<T>.GetEnumerator ()
  269. {
  270. return new Enumerator (this);
  271. }
  272. public struct Enumerator : IEnumerator<T>, IDisposable {
  273. Collection<T> collection;
  274. T current;
  275. int next;
  276. readonly int version;
  277. public T Current {
  278. get { return current; }
  279. }
  280. object IEnumerator.Current {
  281. get {
  282. CheckState ();
  283. if (next <= 0)
  284. throw new InvalidOperationException ();
  285. return current;
  286. }
  287. }
  288. internal Enumerator (Collection<T> collection)
  289. : this ()
  290. {
  291. this.collection = collection;
  292. this.version = collection.version;
  293. }
  294. public bool MoveNext ()
  295. {
  296. CheckState ();
  297. if (next < 0)
  298. return false;
  299. if (next < collection.size) {
  300. current = collection.items [next++];
  301. return true;
  302. }
  303. next = -1;
  304. return false;
  305. }
  306. public void Reset ()
  307. {
  308. CheckState ();
  309. next = 0;
  310. }
  311. void CheckState ()
  312. {
  313. if (collection == null)
  314. throw new ObjectDisposedException (GetType ().FullName);
  315. if (version != collection.version)
  316. throw new InvalidOperationException ();
  317. }
  318. public void Dispose ()
  319. {
  320. collection = null;
  321. }
  322. }
  323. }
  324. }