PageRenderTime 80ms CodeModel.GetById 43ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 0ms

/ndp/fx/src/Core/Microsoft/Scripting/Utils/CollectionExtensions.cs

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