diff --git a/paket-files/gsscoder/CSharpx/src/CSharpx/Either.cs b/paket-files/gsscoder/CSharpx/src/CSharpx/Either.cs index 5bf424b2..b79f4c27 100644 --- a/paket-files/gsscoder/CSharpx/src/CSharpx/Either.cs +++ b/paket-files/gsscoder/CSharpx/src/CSharpx/Either.cs @@ -1,9 +1,9 @@ -//#define CSHARPX_PUBLIC // Comment this to set visibility to internal. -//#define CSHARPX_EITHER_3 // Comment this to remove Either and realted functions. -//#define CSHARPX_EITHER_4 // Comment this to remove Either and realted functions. -//#define CSHARPX_EITHER_5 // Comment this to remove Either and realted functions. -//#define CSHARPX_EITHER_6 // Comment this to remove Either and realted functions. -//#define CSHARPX_EITHER_7 // Comment this to remove Either and realted functions. +#define CSHARPX_PUBLIC // Comment this to set visibility to internal. +#define CSHARPX_EITHER_3 // Comment this to remove Either and realted functions. +#define CSHARPX_EITHER_4 // Comment this to remove Either and realted functions. +#define CSHARPX_EITHER_5 // Comment this to remove Either and realted functions. +#define CSHARPX_EITHER_6 // Comment this to remove Either and realted functions. +#define CSHARPX_EITHER_7 // Comment this to remove Either and realted functions. #define CSHARPX_MAYBE_FUNC // Comment this to remove dependency from Maybe.cs. using System; diff --git a/paket-files/gsscoder/CSharpx/src/CSharpx/EnumerableExtensions.cs b/paket-files/gsscoder/CSharpx/src/CSharpx/EnumerableExtensions.cs new file mode 100644 index 00000000..876e428d --- /dev/null +++ b/paket-files/gsscoder/CSharpx/src/CSharpx/EnumerableExtensions.cs @@ -0,0 +1,332 @@ +// Most methods taken from code.google.com/p/morelinq/. + +#define CSHARPX_PUBLIC // Comment this to set visibility to internal. +#define CSHARPX_CARTESIAN // Comment this to remove Cartesian method. +#define CSHARPX_PREPEND // Comment this to remove Prepend method. +#define CSHARPX_CONCAT // Comment this to remove Concat methods (depend on Prepend). +#define CSHARPX_EXCLUDE // Comment this to remove Prepend method. +#define CSHARPX_INDEX // Comment this to remove Index methods. +#define CSHARPX_FOLD // Comment this to remove Fold methods (depend on Index). +#define CSHARPX_FOREACH // Comment this to remove ForEach method. +#define CSHARPX_PAIRWISE // Comment this to remove Index method. +#define CSHARPX_TODELIMITEDSTRING // Comment this to remove ToDelimitedString methods. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using LinqEnumerable = System.Linq.Enumerable; + +namespace CSharpx +{ +#if CSHARPX_PUBLIC + public +#endif + static partial class EnumerableExtensions + { + private static IEnumerable AssertCountImpl(IEnumerable source, + int count, Func errorSelector) + { + var collection = source as ICollection; // Optimization for collections + if (collection != null) + { + if (collection.Count != count) + throw errorSelector(collection.Count.CompareTo(count), count); + return source; + } + + return ExpectingCountYieldingImpl(source, count, errorSelector); + } + + private static IEnumerable ExpectingCountYieldingImpl(IEnumerable source, + int count, Func errorSelector) + { + var iterations = 0; + foreach (var element in source) + { + iterations++; + if (iterations > count) + { + throw errorSelector(1, count); + } + yield return element; + } + if (iterations != count) + { + throw errorSelector(-1, count); + } + } + +#if CSHARPX_CARTESIAN + /// + /// Returns the Cartesian product of two sequences by combining each element of the first set with each in the second + /// and applying the user=define projection to the pair. + /// + public static IEnumerable Cartesian(this IEnumerable first, IEnumerable second, Func resultSelector) + { + if (first == null) throw new ArgumentNullException("first"); + if (second == null) throw new ArgumentNullException("second"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + return from item1 in first + from item2 in second // TODO buffer to avoid multiple enumerations + select resultSelector(item1, item2); + } +#endif + +#if CSHARPX_PREPEND + /// + /// Prepends a single value to a sequence. + /// + public static IEnumerable Prepend(this IEnumerable source, TSource value) + { + if (source == null) throw new ArgumentNullException("source"); + return LinqEnumerable.Concat(LinqEnumerable.Repeat(value, 1), source); + } +#endif + +#if CSHARPX_CONCAT + /// + /// Returns a sequence consisting of the head element and the given tail elements. + /// + public static IEnumerable Concat(this T head, IEnumerable tail) + { + if (tail == null) throw new ArgumentNullException("tail"); + return tail.Prepend(head); + } + + /// + /// Returns a sequence consisting of the head elements and the given tail element. + /// + public static IEnumerable Concat(this IEnumerable head, T tail) + { + if (head == null) throw new ArgumentNullException("head"); + return LinqEnumerable.Concat(head, LinqEnumerable.Repeat(tail, 1)); + } +#endif + +#if CSHARPX_EXCLUDE + /// + /// Excludes elements from a sequence starting at a given index + /// + /// The type of the elements of the sequence + public static IEnumerable Exclude(this IEnumerable sequence, int startIndex, int count) + { + if (sequence == null) throw new ArgumentNullException("sequence"); + if (startIndex < 0) throw new ArgumentOutOfRangeException("startIndex"); + if (count < 0) throw new ArgumentOutOfRangeException("count"); + + return ExcludeImpl(sequence, startIndex, count); + } + + private static IEnumerable ExcludeImpl(IEnumerable sequence, int startIndex, int count) + { + var index = -1; + var endIndex = startIndex + count; + using (var iter = sequence.GetEnumerator()) + { + // yield the first part of the sequence + while (iter.MoveNext() && ++index < startIndex) + yield return iter.Current; + // skip the next part (up to count items) + while (++index < endIndex && iter.MoveNext()) + continue; + // yield the remainder of the sequence + while (iter.MoveNext()) + yield return iter.Current; + } + } +#endif + +#if CSHARPX_INDEX + /// + /// Returns a sequence of + /// where the key is the zero-based index of the value in the source + /// sequence. + /// + public static IEnumerable> Index(this IEnumerable source) + { + return source.Index(0); + } + + /// + /// Returns a sequence of + /// where the key is the index of the value in the source sequence. + /// An additional parameter specifies the starting index. + /// + public static IEnumerable> Index(this IEnumerable source, int startIndex) + { + return source.Select((item, index) => new KeyValuePair(startIndex + index, item)); + } +#endif + +#if CSHARPX_FOLD + /// + /// Returns the result of applying a function to a sequence of + /// 1 element. + /// + public static TResult Fold(this IEnumerable source, Func folder) + { + return FoldImpl(source, 1, folder, null, null, null); + } + + /// + /// Returns the result of applying a function to a sequence of + /// 2 elements. + /// + public static TResult Fold(this IEnumerable source, Func folder) + { + return FoldImpl(source, 2, null, folder, null, null); + } + + /// + /// Returns the result of applying a function to a sequence of + /// 3 elements. + /// + public static TResult Fold(this IEnumerable source, Func folder) + { + return FoldImpl(source, 3, null, null, folder, null); + } + + /// + /// Returns the result of applying a function to a sequence of + /// 4 elements. + /// + public static TResult Fold(this IEnumerable source, Func folder) + { + return FoldImpl(source, 4, null, null, null, folder); + } + + static TResult FoldImpl(IEnumerable source, int count, + Func folder1, + Func folder2, + Func folder3, + Func folder4) + { + if (source == null) throw new ArgumentNullException("source"); + if (count == 1 && folder1 == null + || count == 2 && folder2 == null + || count == 3 && folder3 == null + || count == 4 && folder4 == null) + { // ReSharper disable NotResolvedInText + throw new ArgumentNullException("folder"); // ReSharper restore NotResolvedInText + } + + var elements = new T[count]; + foreach (var e in AssertCountImpl(source.Index(), count, OnFolderSourceSizeErrorSelector)) + elements[e.Key] = e.Value; + + switch (count) + { + case 1: return folder1(elements[0]); + case 2: return folder2(elements[0], elements[1]); + case 3: return folder3(elements[0], elements[1], elements[2]); + case 4: return folder4(elements[0], elements[1], elements[2], elements[3]); + default: throw new NotSupportedException(); + } + } + + static readonly Func OnFolderSourceSizeErrorSelector = OnFolderSourceSizeError; + + static Exception OnFolderSourceSizeError(int cmp, int count) + { + var message = cmp < 0 + ? "Sequence contains too few elements when exactly {0} {1} expected." + : "Sequence contains too many elements when exactly {0} {1} expected."; + return new Exception(string.Format(message, count.ToString("N0"), count == 1 ? "was" : "were")); + } +#endif + +#if CSHARPX_FOREACH + /// + /// Immediately executes the given action on each element in the source sequence. + /// + /// The type of the elements in the sequence + public static void ForEach(this IEnumerable source, Action action) + { + if (source == null) throw new ArgumentNullException("source"); + if (action == null) throw new ArgumentNullException("action"); + + foreach (var element in source) + { + action(element); + } + } +#endif + +#if CSHARPX_PAIRWISE + /// + /// Returns a sequence resulting from applying a function to each + /// element in the source sequence and its + /// predecessor, with the exception of the first element which is + /// only returned as the predecessor of the second element. + /// + public static IEnumerable Pairwise(this IEnumerable source, Func resultSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + return PairwiseImpl(source, resultSelector); + } + + private static IEnumerable PairwiseImpl(this IEnumerable source, Func resultSelector) + { + Debug.Assert(source != null); + Debug.Assert(resultSelector != null); + + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + yield break; + + var previous = e.Current; + while (e.MoveNext()) + { + yield return resultSelector(previous, e.Current); + previous = e.Current; + } + } + } +#endif + +#if CSHARPX_TODELIMITEDSTRING + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + if (source == null) throw new ArgumentNullException("source"); + return ToDelimitedStringImpl(source, delimiter, (sb, e) => sb.Append(e)); + } + + static string ToDelimitedStringImpl(IEnumerable source, string delimiter, Func append) + { + Debug.Assert(source != null); + Debug.Assert(append != null); + + delimiter = delimiter ?? CultureInfo.CurrentCulture.TextInfo.ListSeparator; + var sb = new StringBuilder(); + var i = 0; + + foreach (var value in source) + { + if (i++ > 0) sb.Append(delimiter); + append(sb, value); + } + + return sb.ToString(); + } +#endif + } +} diff --git a/paket-files/gsscoder/CSharpx/src/CSharpx/Maybe.cs b/paket-files/gsscoder/CSharpx/src/CSharpx/Maybe.cs index 46f74b5e..f19e2da7 100644 --- a/paket-files/gsscoder/CSharpx/src/CSharpx/Maybe.cs +++ b/paket-files/gsscoder/CSharpx/src/CSharpx/Maybe.cs @@ -1,4 +1,4 @@ -//#define CSHARPX_PUBLIC // Comment this to set visibility to internal. +#define CSHARPX_PUBLIC // Comment this to set visibility to internal. #define CSHARPX_EITHER_FUNC // Comment this to remove dependency from Either.cs. using System; diff --git a/paket-files/gsscoder/CSharpx/src/CSharpx/paket.version b/paket-files/gsscoder/CSharpx/src/CSharpx/paket.version index b0cca172..cc16163f 100644 --- a/paket-files/gsscoder/CSharpx/src/CSharpx/paket.version +++ b/paket-files/gsscoder/CSharpx/src/CSharpx/paket.version @@ -1 +1 @@ -d2ecc2810fe4e29b62934e51242f98f1e47f3a79 +5c88658b2553e59b3aa989660dc1e36c48673af5 diff --git a/paket.dependencies b/paket.dependencies index f6479c2f..ed9a1996 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -7,3 +7,4 @@ nuget xunit.runner.visualstudio github gsscoder/CSharpx src/CSharpx/Maybe.cs github gsscoder/CSharpx src/CSharpx/Either.cs +github gsscoder/CSharpx src/CSharpx/EnumerableExtensions.cs diff --git a/paket.lock b/paket.lock index b69383df..4138ce3b 100644 --- a/paket.lock +++ b/paket.lock @@ -16,5 +16,6 @@ NUGET GITHUB remote: gsscoder/CSharpx specs: - src/CSharpx/Either.cs (d2ecc2810fe4e29b62934e51242f98f1e47f3a79) - src/CSharpx/Maybe.cs (d2ecc2810fe4e29b62934e51242f98f1e47f3a79) \ No newline at end of file + src/CSharpx/Either.cs (5c88658b2553e59b3aa989660dc1e36c48673af5) + src/CSharpx/EnumerableExtensions.cs (5c88658b2553e59b3aa989660dc1e36c48673af5) + src/CSharpx/Maybe.cs (5c88658b2553e59b3aa989660dc1e36c48673af5) \ No newline at end of file diff --git a/src/CommandLine/CommandLine.csproj b/src/CommandLine/CommandLine.csproj index 6f6df341..3aedeceb 100644 --- a/src/CommandLine/CommandLine.csproj +++ b/src/CommandLine/CommandLine.csproj @@ -42,6 +42,10 @@ ..\..\CommandLine.snk + + True + Infrastructure/EnumerableExtensions.cs + True Infrastructure/Either.cs @@ -76,7 +80,7 @@ - + Code diff --git a/src/CommandLine/paket.references b/src/CommandLine/paket.references index 3f2e183a..0b555821 100644 --- a/src/CommandLine/paket.references +++ b/src/CommandLine/paket.references @@ -1,3 +1,4 @@ File:Maybe.cs Infrastructure File:Either.cs Infrastructure +File:EnumerableExtensions.cs Infrastructure FSharp.Core