1using System;
2using System.Collections.Generic;
3using System.Text;
4
5// Taken from Mono sources, changed to work on C# 2.0 compilers
6
7//
8// Enumerable.cs
9//
10// Authors:
11//  Marek Safar (marek.safar@gmail.com)
12//  Antonello Provenzano  <antonello@deveel.com>
13//  Alejandro Serrano "Serras" (trupill@yahoo.es)
14//  Jb Evain (jbevain@novell.com)
15//
16// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
17//
18// Permission is hereby granted, free of charge, to any person obtaining
19// a copy of this software and associated documentation files (the
20// "Software"), to deal in the Software without restriction, including
21// without limitation the rights to use, copy, modify, merge, publish,
22// distribute, sublicense, and/or sell copies of the Software, and to
23// permit persons to whom the Software is furnished to do so, subject to
24// the following conditions:
25//
26// The above copyright notice and this permission notice shall be
27// included in all copies or substantial portions of the Software.
28//
29// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36//
37
38// precious: http://www.hookedonlinq.com
39
40public delegate TResult Func<TResult>();
41public delegate TResult Func<T, TResult>(T arg1);
42public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
43public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
44public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
45
46
47namespace Antlr.Runtime.JavaExtensions {
48    static class EnumerableExtensions {
49
50        #region Average
51
52        public static double Average(IEnumerable<int> source) {
53            return Average<int, long, double>(source, delegate(long a, int b) { return a + b; }, delegate(long a, long b) { return (double)a / (double)b; });
54        }
55
56        static TResult Average<TElement, TAggregate, TResult>(IEnumerable<TElement> source,
57            Func<TAggregate, TElement, TAggregate> func, Func<TAggregate, long, TResult> result)
58            where TElement : struct
59            where TAggregate : struct
60            where TResult : struct {
61            Check.Source(source);
62
63            var total = default(TAggregate);
64            long counter = 0;
65            foreach (var element in source) {
66                total = func(total, element);
67                ++counter;
68            }
69
70            if (counter == 0)
71                throw new InvalidOperationException();
72
73            return result(total, counter);
74        }
75
76        public static double Average(IEnumerable<double> source) {
77            return Average<double, double, double>(source, delegate(double a, double b) { return a + b; }, delegate(double a, long b) { return a / b; });
78        }
79
80        #endregion
81
82        #region Contains
83
84        public static bool Contains<TSource>(IEnumerable<TSource> source, TSource value) {
85            var collection = source as ICollection<TSource>;
86            if (collection != null)
87                return collection.Contains(value);
88
89            return Contains<TSource>(source, value, null);
90        }
91
92        public static bool Contains<TSource>(IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer) {
93            Check.Source(source);
94
95            if (comparer == null)
96                comparer = EqualityComparer<TSource>.Default;
97
98            foreach (var element in source)
99                if (comparer.Equals(element, value))
100                    return true;
101
102            return false;
103        }
104        #endregion
105
106        #region DefaultIfEmpty
107
108        public static IEnumerable<TSource> DefaultIfEmpty<TSource>(IEnumerable<TSource> source) {
109            return DefaultIfEmpty(source, default(TSource));
110        }
111
112        public static IEnumerable<TSource> DefaultIfEmpty<TSource>(IEnumerable<TSource> source, TSource defaultValue) {
113            Check.Source(source);
114
115            return CreateDefaultIfEmptyIterator(source, defaultValue);
116        }
117
118        static IEnumerable<TSource> CreateDefaultIfEmptyIterator<TSource>(IEnumerable<TSource> source, TSource defaultValue) {
119            bool empty = true;
120            foreach (TSource item in source) {
121                empty = false;
122                yield return item;
123            }
124
125            if (empty)
126                yield return defaultValue;
127        }
128
129        #endregion
130
131        #region Max
132
133        public static int Max(IEnumerable<int> source) {
134            Check.Source(source);
135
136            return Iterate(source, int.MinValue, delegate(int a, int b){return Math.Max(a, b);});
137        }
138
139        static U Iterate<T, U>(IEnumerable<T> source, U initValue, Func<T, U, U> selector) {
140            bool empty = true;
141            foreach (var element in source) {
142                initValue = selector(element, initValue);
143                empty = false;
144            }
145
146            if (empty)
147                throw new InvalidOperationException();
148
149            return initValue;
150        }
151
152        #endregion
153
154        #region Min
155
156        public static int Min(IEnumerable<int> source) {
157            Check.Source(source);
158
159            return Iterate(source, int.MaxValue, delegate(int a, int b) { return Math.Min(a, b); });
160        }
161
162        #endregion
163
164        #region Select
165
166        public static IEnumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector) {
167            Check.SourceAndSelector(source, selector);
168
169            return CreateSelectIterator(source, selector);
170        }
171
172        static IEnumerable<TResult> CreateSelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector) {
173            foreach (var element in source)
174                yield return selector(element);
175        }
176
177        public static IEnumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) {
178            Check.SourceAndSelector(source, selector);
179
180            return CreateSelectIterator(source, selector);
181        }
182
183        static IEnumerable<TResult> CreateSelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) {
184            int counter = 0;
185            foreach (TSource element in source) {
186                yield return selector(element, counter);
187                counter++;
188            }
189        }
190
191        #endregion
192
193        #region SelectMany
194
195        public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(IEnumerable<TSource> source,
196            Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector) {
197            Check.SourceAndCollectionSelectors(source, collectionSelector, selector);
198
199            return CreateSelectManyIterator(source, collectionSelector, selector);
200        }
201
202        public static IEnumerable<TResult> SelectMany<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector) {
203            Check.SourceAndSelector(source, selector);
204
205            return CreateSelectManyIterator(source, selector);
206        }
207
208        static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult>(IEnumerable<TSource> source,
209            Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector) {
210            int counter = 0;
211            foreach (TSource element in source)
212                foreach (TCollection collection in collectionSelector(element, counter++))
213                    yield return selector(element, collection);
214        }
215
216        static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector) {
217            int counter = 0;
218            foreach (TSource element in source) {
219                foreach (TResult item in selector(element, counter))
220                    yield return item;
221                counter++;
222            }
223        }
224
225        #endregion
226
227        #region Sum
228
229        public static int Sum(IEnumerable<int> source) {
230            Check.Source(source);
231
232            return Sum<int, int>(source, delegate(int a, int b) { return checked(a + b); });
233        }
234
235        static TR Sum<TA, TR>(IEnumerable<TA> source, Func<TR, TA, TR> selector) {
236            TR total = default(TR);
237            foreach (var element in source) {
238                total = selector(total, element);
239            }
240
241            return total;
242        }
243
244        #endregion
245
246        #region Take
247
248        public static IEnumerable<TSource> Take<TSource>(IEnumerable<TSource> source, int count) {
249            Check.Source(source);
250
251            return CreateTakeIterator(source, count);
252        }
253
254        static IEnumerable<TSource> CreateTakeIterator<TSource>(IEnumerable<TSource> source, int count) {
255            if (count <= 0)
256                yield break;
257
258            int counter = 0;
259            foreach (TSource element in source) {
260                yield return element;
261
262                if (++counter == count)
263                    yield break;
264            }
265        }
266
267        #endregion
268
269        #region ToArray
270
271        public static TSource[] ToArray<TSource>(IEnumerable<TSource> source) {
272            Check.Source(source);
273
274            var collection = source as ICollection<TSource>;
275            if (collection != null) {
276                var array = new TSource[collection.Count];
277                collection.CopyTo(array, 0);
278                return array;
279            }
280
281            return new List<TSource>(source).ToArray();
282        }
283
284        #endregion
285    }
286}
287