System.Drawing: added email to icon and test file headers
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Utils / CollectionExtensions.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
6  * copy of the license can be found in the License.html file at the root of this distribution. If 
7  * you cannot locate the  Apache License, Version 2.0, please send an email to 
8  * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
9  * by the terms of the Apache License, Version 2.0.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 #if CLR2
17 using Microsoft.Scripting.Utils;
18 using Microsoft.Scripting.Ast;
19 #else
20 using System.Diagnostics.Contracts;
21 using System.Linq.Expressions;
22 #endif
23
24 using System.Collections.Generic;
25 using System.Collections.ObjectModel;
26 using System.Diagnostics;
27 using System.Runtime.CompilerServices;
28
29 namespace System.Dynamic.Utils {
30     internal static class CollectionExtensions {
31         /// <summary>
32         /// Wraps the provided enumerable into a ReadOnlyCollection{T}
33         /// 
34         /// Copies all of the data into a new array, so the data can't be
35         /// changed after creation. The exception is if the enumerable is
36         /// already a ReadOnlyCollection{T}, in which case we just return it.
37         /// </summary>
38 #if !CLR2
39         [Pure]
40 #endif
41         internal static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> enumerable) {
42             if (enumerable == null) {
43                 return EmptyReadOnlyCollection<T>.Instance;
44             }
45
46 #if SILVERLIGHT
47             if (Expression.SilverlightQuirks) {
48                 // Allow any ReadOnlyCollection to be stored directly
49                 // (even though this is not safe)
50                 var r = enumerable as ReadOnlyCollection<T>;
51                 if (r != null) {
52                     return r;
53                 }
54             }
55 #endif
56
57             var troc = enumerable as TrueReadOnlyCollection<T>;
58             if (troc != null) {
59                 return troc;
60             }
61
62             var builder = enumerable as ReadOnlyCollectionBuilder<T>;
63             if (builder != null) {
64                 return builder.ToReadOnlyCollection();
65             }
66
67             var collection = enumerable as ICollection<T>;
68             if (collection != null) {
69                 int count = collection.Count;
70                 if (count == 0) {
71                     return EmptyReadOnlyCollection<T>.Instance;
72                 }
73
74                 T[] clone = new T[count];
75                 collection.CopyTo(clone, 0);
76                 return new TrueReadOnlyCollection<T>(clone);
77             }
78
79             // ToArray trims the excess space and speeds up access
80             return new TrueReadOnlyCollection<T>(new List<T>(enumerable).ToArray());
81         }
82
83         // We could probably improve the hashing here
84         internal static int ListHashCode<T>(this IEnumerable<T> list) {
85             var cmp = EqualityComparer<T>.Default;
86             int h = 6551;
87             foreach (T t in list) {
88                 h ^= (h << 5) ^ cmp.GetHashCode(t);
89             }
90             return h;
91         }
92
93 #if !CLR2
94         [Pure]
95 #endif
96         internal static bool ListEquals<T>(this ICollection<T> first, ICollection<T> second) {
97             if (first.Count != second.Count) {
98                 return false;
99             }
100             var cmp = EqualityComparer<T>.Default;
101             var f = first.GetEnumerator();
102             var s = second.GetEnumerator();
103             while (f.MoveNext()) {
104                 s.MoveNext();
105
106                 if (!cmp.Equals(f.Current, s.Current)) {
107                     return false;
108                 }
109             }
110             return true;
111         }
112
113         internal static IEnumerable<U> Select<T, U>(this IEnumerable<T> enumerable, Func<T, U> select) {
114             foreach (T t in enumerable) {
115                 yield return select(t);
116             }
117         }
118
119         // Name needs to be different so it doesn't conflict with Enumerable.Select
120         internal static U[] Map<T, U>(this ICollection<T> collection, Func<T, U> select) {
121             int count = collection.Count;
122             U[] result = new U[count];
123             count = 0;
124             foreach (T t in collection) {
125                 result[count++] = select(t);
126             }
127             return result;
128         }
129
130         internal static IEnumerable<T> Where<T>(this IEnumerable<T> enumerable, Func<T, bool> where) {
131             foreach (T t in enumerable) {
132                 if (where(t)) {
133                     yield return t;
134                 }
135             }
136         }
137
138         internal static bool Any<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
139             foreach (T element in source) {
140                 if (predicate(element)) {
141                     return true;
142                 }
143             }
144             return false;
145         }
146
147         internal static bool All<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
148             foreach (T element in source) {
149                 if (!predicate(element)) {
150                     return false;
151                 }
152             }
153             return true;
154         }
155
156         internal static T[] RemoveFirst<T>(this T[] array) {
157             T[] result = new T[array.Length - 1];
158             Array.Copy(array, 1, result, 0, result.Length);
159             return result;
160         }
161
162         internal static T[] RemoveLast<T>(this T[] array) {
163             T[] result = new T[array.Length - 1];
164             Array.Copy(array, 0, result, 0, result.Length);
165             return result;
166         }
167
168         internal static T[] AddFirst<T>(this IList<T> list, T item) {
169             T[] res = new T[list.Count + 1];
170             res[0] = item;
171             list.CopyTo(res, 1);
172             return res;
173         }
174
175         internal static T[] AddLast<T>(this IList<T> list, T item) {
176             T[] res = new T[list.Count + 1];
177             list.CopyTo(res, 0);
178             res[list.Count] = item;
179             return res;
180         }
181
182         internal static T First<T>(this IEnumerable<T> source) {
183             var list = source as IList<T>;
184             if (list != null) {
185                 return list[0];
186             }
187             using (var e = source.GetEnumerator()) {
188                 if (e.MoveNext()) return e.Current;
189             }
190             throw new InvalidOperationException();
191         }
192
193         internal static T Last<T>(this IList<T> list) {
194             return list[list.Count - 1];
195         }
196
197         internal static T[] Copy<T>(this T[] array) {
198             T[] copy = new T[array.Length];
199             Array.Copy(array, copy, array.Length);
200             return copy;
201         }
202     }
203
204
205     internal static class EmptyReadOnlyCollection<T> {
206         internal static ReadOnlyCollection<T> Instance = new TrueReadOnlyCollection<T>(new T[0]);
207     }
208 }