/Mono.Cecil/Mono.Collections.Generic/Collection.cs

http://github.com/icsharpcode/ILSpy · C# · 420 lines · 304 code · 89 blank · 27 comment · 28 complexity · c02b2ecacd394f8ef989d3185336f29a MD5 · raw file

  1. //
  2. // Collection.cs
  3. //
  4. // Author:
  5. // Jb Evain (jbevain@gmail.com)
  6. //
  7. // Copyright (c) 2008 - 2011 Jb Evain
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.Collections;
  30. using System.Collections.Generic;
  31. namespace Mono.Collections.Generic {
  32. public class Collection<T> : IList<T>, IList {
  33. internal T [] items;
  34. internal int size;
  35. int version;
  36. public int Count {
  37. get { return size; }
  38. }
  39. public T this [int index] {
  40. get {
  41. if (index >= size)
  42. throw new ArgumentOutOfRangeException ();
  43. return items [index];
  44. }
  45. set {
  46. CheckIndex (index);
  47. if (index == size)
  48. throw new ArgumentOutOfRangeException ();
  49. OnSet (value, index);
  50. items [index] = value;
  51. }
  52. }
  53. bool ICollection<T>.IsReadOnly {
  54. get { return false; }
  55. }
  56. bool IList.IsFixedSize {
  57. get { return false; }
  58. }
  59. bool IList.IsReadOnly {
  60. get { return false; }
  61. }
  62. object IList.this [int index] {
  63. get { return this [index]; }
  64. set {
  65. CheckIndex (index);
  66. try {
  67. this [index] = (T) value;
  68. return;
  69. } catch (InvalidCastException) {
  70. } catch (NullReferenceException) {
  71. }
  72. throw new ArgumentException ();
  73. }
  74. }
  75. int ICollection.Count {
  76. get { return Count; }
  77. }
  78. bool ICollection.IsSynchronized {
  79. get { return false; }
  80. }
  81. object ICollection.SyncRoot {
  82. get { return this; }
  83. }
  84. public Collection ()
  85. {
  86. items = Empty<T>.Array;
  87. }
  88. public Collection (int capacity)
  89. {
  90. if (capacity < 0)
  91. throw new ArgumentOutOfRangeException ();
  92. items = new T [capacity];
  93. }
  94. public Collection (ICollection<T> items)
  95. {
  96. if (items == null)
  97. throw new ArgumentNullException ("items");
  98. this.items = new T [items.Count];
  99. items.CopyTo (this.items, 0);
  100. this.size = this.items.Length;
  101. }
  102. public void Add (T item)
  103. {
  104. if (size == items.Length)
  105. Grow (1);
  106. OnAdd (item, size);
  107. items [size++] = item;
  108. version++;
  109. }
  110. public bool Contains (T item)
  111. {
  112. return IndexOf (item) != -1;
  113. }
  114. public int IndexOf (T item)
  115. {
  116. return Array.IndexOf (items, item, 0, size);
  117. }
  118. public void Insert (int index, T item)
  119. {
  120. CheckIndex (index);
  121. if (size == items.Length)
  122. Grow (1);
  123. OnInsert (item, index);
  124. Shift (index, 1);
  125. items [index] = item;
  126. version++;
  127. }
  128. public void RemoveAt (int index)
  129. {
  130. if (index < 0 || index >= size)
  131. throw new ArgumentOutOfRangeException ();
  132. var item = items [index];
  133. OnRemove (item, index);
  134. Shift (index, -1);
  135. Array.Clear (items, size, 1);
  136. version++;
  137. }
  138. public bool Remove (T item)
  139. {
  140. var index = IndexOf (item);
  141. if (index == -1)
  142. return false;
  143. OnRemove (item, index);
  144. Shift (index, -1);
  145. Array.Clear (items, size, 1);
  146. version++;
  147. return true;
  148. }
  149. public void Clear ()
  150. {
  151. OnClear ();
  152. Array.Clear (items, 0, size);
  153. size = 0;
  154. version++;
  155. }
  156. public void CopyTo (T [] array, int arrayIndex)
  157. {
  158. Array.Copy (items, 0, array, arrayIndex, size);
  159. }
  160. public T [] ToArray ()
  161. {
  162. var array = new T [size];
  163. Array.Copy (items, 0, array, 0, size);
  164. return array;
  165. }
  166. void CheckIndex (int index)
  167. {
  168. if (index < 0 || index > size)
  169. throw new ArgumentOutOfRangeException ();
  170. }
  171. void Shift (int start, int delta)
  172. {
  173. if (delta < 0)
  174. start -= delta;
  175. if (start < size)
  176. Array.Copy (items, start, items, start + delta, size - start);
  177. size += delta;
  178. if (delta < 0)
  179. Array.Clear (items, size, -delta);
  180. }
  181. protected virtual void OnAdd (T item, int index)
  182. {
  183. }
  184. protected virtual void OnInsert (T item, int index)
  185. {
  186. }
  187. protected virtual void OnSet (T item, int index)
  188. {
  189. }
  190. protected virtual void OnRemove (T item, int index)
  191. {
  192. }
  193. protected virtual void OnClear ()
  194. {
  195. }
  196. internal virtual void Grow (int desired)
  197. {
  198. int new_size = size + desired;
  199. if (new_size <= items.Length)
  200. return;
  201. const int default_capacity = 4;
  202. new_size = System.Math.Max (
  203. System.Math.Max (items.Length * 2, default_capacity),
  204. new_size);
  205. #if !CF
  206. Array.Resize (ref items, new_size);
  207. #else
  208. var array = new T [new_size];
  209. Array.Copy (items, array, size);
  210. items = array;
  211. #endif
  212. }
  213. int IList.Add (object value)
  214. {
  215. try {
  216. Add ((T) value);
  217. return size - 1;
  218. } catch (InvalidCastException) {
  219. } catch (NullReferenceException) {
  220. }
  221. throw new ArgumentException ();
  222. }
  223. void IList.Clear ()
  224. {
  225. Clear ();
  226. }
  227. bool IList.Contains (object value)
  228. {
  229. return ((IList) this).IndexOf (value) > -1;
  230. }
  231. int IList.IndexOf (object value)
  232. {
  233. try {
  234. return IndexOf ((T) value);
  235. } catch (InvalidCastException) {
  236. } catch (NullReferenceException) {
  237. }
  238. return -1;
  239. }
  240. void IList.Insert (int index, object value)
  241. {
  242. CheckIndex (index);
  243. try {
  244. Insert (index, (T) value);
  245. return;
  246. } catch (InvalidCastException) {
  247. } catch (NullReferenceException) {
  248. }
  249. throw new ArgumentException ();
  250. }
  251. void IList.Remove (object value)
  252. {
  253. try {
  254. Remove ((T) value);
  255. } catch (InvalidCastException) {
  256. } catch (NullReferenceException) {
  257. }
  258. }
  259. void IList.RemoveAt (int index)
  260. {
  261. RemoveAt (index);
  262. }
  263. void ICollection.CopyTo (Array array, int index)
  264. {
  265. Array.Copy (items, 0, array, index, size);
  266. }
  267. public Enumerator GetEnumerator ()
  268. {
  269. return new Enumerator (this);
  270. }
  271. IEnumerator IEnumerable.GetEnumerator ()
  272. {
  273. return new Enumerator (this);
  274. }
  275. IEnumerator<T> IEnumerable<T>.GetEnumerator ()
  276. {
  277. return new Enumerator (this);
  278. }
  279. public struct Enumerator : IEnumerator<T>, IDisposable {
  280. Collection<T> collection;
  281. T current;
  282. int next;
  283. readonly int version;
  284. public T Current {
  285. get { return current; }
  286. }
  287. object IEnumerator.Current {
  288. get {
  289. CheckState ();
  290. if (next <= 0)
  291. throw new InvalidOperationException ();
  292. return current;
  293. }
  294. }
  295. internal Enumerator (Collection<T> collection)
  296. : this ()
  297. {
  298. this.collection = collection;
  299. this.version = collection.version;
  300. }
  301. public bool MoveNext ()
  302. {
  303. CheckState ();
  304. if (next < 0)
  305. return false;
  306. if (next < collection.size) {
  307. current = collection.items [next++];
  308. return true;
  309. }
  310. next = -1;
  311. return false;
  312. }
  313. public void Reset ()
  314. {
  315. CheckState ();
  316. next = 0;
  317. }
  318. void CheckState ()
  319. {
  320. if (collection == null)
  321. throw new ObjectDisposedException (GetType ().FullName);
  322. if (version != collection.version)
  323. throw new InvalidOperationException ();
  324. }
  325. public void Dispose ()
  326. {
  327. collection = null;
  328. }
  329. }
  330. }
  331. }