2008-05-01 Jb Evain <jbevain@novell.com>
authorJb Evain <jbevain@gmail.com>
Thu, 1 May 2008 20:21:56 +0000 (20:21 -0000)
committerJb Evain <jbevain@gmail.com>
Thu, 1 May 2008 20:21:56 +0000 (20:21 -0000)
* SortDirection.cs, SortContext.cs, SortSequenceContext.cs:
new infrastructure files for nested orderby/thenby calls.
* QuickSort.cs: refactored out of OrderedSequence.cs
* OrderedEnumerable.cs, OrderedSequence.cs: refactoring
to use the new SortContext infrastructure.

svn path=/trunk/mcs/; revision=102297

mcs/class/System.Core/ChangeLog
mcs/class/System.Core/System.Core-2008.csproj
mcs/class/System.Core/System.Core.dll.sources
mcs/class/System.Core/System.Linq/ChangeLog
mcs/class/System.Core/System.Linq/Enumerable.cs
mcs/class/System.Core/System.Linq/OrderedEnumerable.cs
mcs/class/System.Core/System.Linq/OrderedSequence.cs
mcs/class/System.Core/System.Linq/QuickSort.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/SortContext.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/SortDirection.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/SortSequenceContext.cs [new file with mode: 0644]

index eb78d6d8629ff15c26328fdadb16fa12b8f29725..5fde911341f18f6a1444105ebb671b3e714f27a5 100644 (file)
@@ -1,3 +1,7 @@
+2008-05-01  Jb Evain  <jbevain@novell.com>
+
+       * System.Core-2008.csproj, System.Core.dll.sources: add new files.
+
 2008-03-27  Leonid Freydovich  <leonidf@mainsoft.com>
 
        * Add some TARGET_JVM specific code
@@ -10,7 +14,7 @@
 2007-12-04  Marek Safar  <marek.safar@gmail.com>
 
        * System.Core.dll.sources: System.Linq.Expression refresh.
-       
+
 2007-08-20  Marek Safar  <marek.safar@gmail.com>
 
        * Makefile: Hardcoded 3.5 define for now.
@@ -27,7 +31,7 @@
        * Implemented somme missing stuff in BinaryExpression.
 
        * The stuff in ExpressionUtils is very generic and does quite some
-       redundant checks: I started splitting the stuff there into more   
+       redundant checks: I started splitting the stuff there into more
        "specific" methods that should be both understandable and fast.
 
        * Fixed the StringBuilder problem, added unique IDs to all tests,
@@ -59,7 +63,7 @@
 2007-03-29  Miguel de Icaza  <miguel@novell.com>
 
        * Reapply the patch from Antonello, and rework the code to not use
-       extension methods on Enumerable. 
+       extension methods on Enumerable.
 
 2007-02-04  Marek Safar  <marek.safar@gmail.com>
 
index 79edfabb399b5b6514b948539782876386f28cf2..4f1cf58f6537102aa7a8675fbe1c3ab386df1c44 100755 (executable)
     <Compile Include="System.Linq.Expressions\TypeBinaryExpression.cs" />\r
     <Compile Include="System.Linq.Expressions\UnaryExpression.cs" />\r
     <Compile Include="System.Linq\Check.cs" />\r
+    <Compile Include="System.Linq\QuickSort.cs" />\r
+    <Compile Include="System.Linq\SortSequenceContext.cs" />\r
+    <Compile Include="System.Linq\SortContext.cs" />\r
     <Compile Include="System.Linq\Enumerable.cs" />\r
+    <Compile Include="System.Linq\SortDirection.cs" />\r
     <Compile Include="System.Linq\Grouping.cs" />\r
     <Compile Include="System.Linq\IGrouping.cs" />\r
     <Compile Include="System.Linq\ILookup_T.cs" />\r
index 8a2c80ef855375377ff5622ef4e660e881f82678..fbd78daa6ba058cad4139e2b562fe5571ccc5842 100644 (file)
@@ -17,7 +17,6 @@ System.Linq/Check.cs
 System.Linq/Enumerable.cs
 System.Linq/Grouping.cs
 System.Linq/IGrouping.cs
-System.Linq/OrderedSequence.cs
 System.Linq/IOrderedQueryable.cs
 System.Linq/IOrderedQueryable_T.cs
 System.Linq/IOrderedEnumerable_T.cs
@@ -26,7 +25,12 @@ System.Linq/IQueryable_T.cs
 System.Linq/Lookup.cs
 System.Linq/ILookup_T.cs
 System.Linq/OrderedEnumerable.cs
+System.Linq/OrderedSequence.cs
 System.Linq/Queryable.cs
+System.Linq/QuickSort.cs
+System.Linq/SortContext.cs
+System.Linq/SortDirection.cs
+System.Linq/SortSequenceContext.cs
 System.Linq/IQueryProvider.cs
 System.Linq.Expressions/BinaryExpression.cs
 System.Linq.Expressions/ConditionalExpression.cs
index 812f8408f94f8eabde63308a613ae4616dd2dd73..907ca5f2c9c9ab2331114764cf31602e2f45586f 100644 (file)
@@ -1,3 +1,11 @@
+2008-05-01  Jb Evain  <jbevain@novell.com>
+
+       * SortDirection.cs, SortContext.cs, SortSequenceContext.cs:
+       new infrastructure files for nested orderby/thenby calls.
+       * QuickSort.cs: refactored out of OrderedSequence.cs
+       * OrderedEnumerable.cs, OrderedSequence.cs: refactoring
+       to use the new SortContext infrastructure.
+
 2008-04-30  Jb Evain  <jbevain@novell.com>
 
        * Enumerable.cs: Average (int|long): properly compute
index d243ff7c327e53b54ab0c76581c67096c7878eae..3cad6b08da7707553e4fc8e4dcfd0993157b6580 100644 (file)
@@ -1603,7 +1603,6 @@ namespace System.Linq
                        return OrderBy<TSource, TKey> (source, keySelector, null);
                }
 
-
                public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
                                Func<TSource, TKey> keySelector,
                                IComparer<TKey> comparer)
@@ -1611,7 +1610,7 @@ namespace System.Linq
                        Check.SourceAndKeySelector (source, keySelector);
 
                        return new OrderedSequence<TSource, TKey> (
-                                       source, keySelector, comparer, false);
+                                       source, keySelector, comparer, SortDirection.Ascending);
                }
 
                #endregion
@@ -1624,14 +1623,13 @@ namespace System.Linq
                        return OrderByDescending<TSource, TKey> (source, keySelector, null);
                }
 
-
                public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
                                Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
                {
                        Check.SourceAndKeySelector (source, keySelector);
 
                        return new OrderedSequence<TSource, TKey> (
-                                       source, keySelector, comparer, true);
+                                       source, keySelector, comparer, SortDirection.Descending);
                }
 
                #endregion
@@ -2207,7 +2205,6 @@ namespace System.Linq
                        return ThenBy<TSource, TKey> (source, keySelector, null);
                }
 
-
                public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
                        Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
                {
@@ -2226,7 +2223,6 @@ namespace System.Linq
                        return ThenByDescending<TSource, TKey> (source, keySelector, null);
                }
 
-
                public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
                        Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
                {
index 313844f29f86301a6d89d35580b07bf74bd7b8fd..b7e90f2ba51d86f39cc3e135ac6177b248fafd8a 100644 (file)
@@ -3,8 +3,9 @@
 //
 // Authors:
 //     Marek Safar  <marek.safar@gmail.com>
+//     Jb Evain  <jbevain@novell.com>
 //
-// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2007 - 2008 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -34,21 +35,32 @@ namespace System.Linq {
 
        abstract class OrderedEnumerable<TElement> : IOrderedEnumerable<TElement> {
 
-               protected OrderedEnumerable<TElement> parent;
+               IEnumerable<TElement> source;
 
-               public abstract IEnumerator<TElement> GetEnumerator ();
-               public abstract IEnumerable<TElement> Sort (IEnumerable<TElement> parentSource);
+               protected OrderedEnumerable (IEnumerable<TElement> source)
+               {
+                       this.source = source;
+               }
 
                IEnumerator IEnumerable.GetEnumerator ()
                {
                        return GetEnumerator ();
                }
-                        
+
+               public IEnumerator<TElement> GetEnumerator ()
+               {
+                       return Sort (source).GetEnumerator ();
+               }
+
+               public abstract SortContext<TElement> CreateContext (SortContext<TElement> current);
+
+               protected abstract IEnumerable<TElement> Sort (IEnumerable<TElement> source);
+
                public IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey> (
                        Func<TElement, TKey> selector, IComparer<TKey> comparer, bool descending)
                {
-                       parent = new OrderedSequence<TElement, TKey> (this, selector, comparer, descending);
-                       return parent;
+                       return new OrderedSequence<TElement, TKey> (this, source, selector, comparer,
+                               descending ? SortDirection.Descending : SortDirection.Ascending);
                }
        }
 }
index dfc38ee8310270b33b51e7b0a2277940619f2087..62bd024477b5a81edc01b88f2861de5b1165b00a 100644 (file)
@@ -4,6 +4,7 @@
 // Authors:
 //     Alejandro Serrano "Serras" (trupill@yahoo.es)
 //     Marek Safar  <marek.safar@gmail.com>
+//     Jb Evain  <jbevain@novell.com>
 //
 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
 //
@@ -33,132 +34,41 @@ using System.Collections.Generic;
 
 namespace System.Linq {
 
-       sealed class OrderedSequence<TElement, TKey> : OrderedEnumerable<TElement> {
+       class OrderedSequence<TElement, TKey> : OrderedEnumerable<TElement> {
 
-               readonly IEnumerable<TElement> source;
-               readonly Func<TElement, TKey> key_selector;
-               readonly IComparer<TKey> comparer;
-               readonly bool descending;
+               OrderedEnumerable<TElement> parent;
 
-               List<TElement> source_list;
-               TKey [] keys;
-               int [] indexes;
+               Func<TElement, TKey> selector;
+               IComparer<TKey> comparer;
+               SortDirection direction;
 
-               internal OrderedSequence (IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
+               internal OrderedSequence (IEnumerable<TElement> source, Func<TElement, TKey> key_selector, IComparer<TKey> comparer, SortDirection direction)
+                       : base (source)
                {
-                       this.source = source;
-                       this.key_selector = keySelector;
+                       this.selector = key_selector;
                        this.comparer = comparer ?? Comparer<TKey>.Default;
-                       this.descending = descending;
+                       this.direction = direction;
                }
 
-               public override IEnumerable<TElement> Sort (IEnumerable<TElement> parentSource)
+               internal OrderedSequence (OrderedEnumerable<TElement> parent, IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, SortDirection direction)
+                       : this (source, keySelector, comparer, direction)
                {
-                       if (parent != null)
-                               return parent.Sort (source);
-
-                       return PerformSort (parentSource);
-               }
-
-               public override IEnumerator<TElement> GetEnumerator ()
-               {
-                       return PerformSort (source).GetEnumerator ();
-               }
-
-               IEnumerable<TElement> PerformSort (IEnumerable<TElement> items)
-               {
-                       // It first enumerates source, collecting all elements
-                       source_list = new List<TElement> (items);
-
-                       // If the source contains just zero or one element, there's no need to sort
-                       if (source_list.Count <= 1)
-                               return source_list;
-
-                       // Then evaluate the keySelector function for each element,
-                       // collecting the key values
-                       keys = new TKey [source_list.Count];
-                       indexes = new int [source_list.Count];
-                       for (int i = 0; i < source_list.Count; i++) {
-                               keys [i] = key_selector (source_list [i]);
-                               indexes [i] = i;
-                       }
-
-                       // Then sorts the elements according to the collected
-                       // key values and the selected ordering
-                       QuickSort (0, indexes.Length - 1);
-
-                       // Return the values as IEnumerable<TElement>
-                       TElement [] ordered = new TElement [indexes.Length];
-                       for (int i = 0; i < indexes.Length; i++)
-                               ordered [i] = source_list [indexes [i]];
-
-                       return ordered;
+                       this.parent = parent;
                }
 
-               int CompareItems (int firstIndex, int secondIndex)
+               public override SortContext<TElement> CreateContext (SortContext<TElement> current)
                {
-                       int comparison = comparer.Compare (keys [firstIndex], keys [secondIndex]);
+                       SortContext<TElement> context = new SortSequenceContext<TElement, TKey> (selector, comparer, direction, current);
 
-                       // If descending, return the opposite comparison
-                       return (descending ? -comparison : comparison);
-               }
-
-               // We look at the first, middle, and last items in the subarray.
-               // Then we put the largest on the right side, the smallest on
-               // the left side, and the median becomes our pivot.
-               int MedianOfThree (int left, int right)
-               {
-                       int center = (left + right) / 2;
-                       if (CompareItems (indexes [center], indexes [left]) < 0)
-                               Swap (left, center);
-                       if (CompareItems (indexes [right], indexes [left]) < 0)
-                               Swap (left, right);
-                       if (CompareItems (indexes [right], indexes [center]) < 0)
-                               Swap (center, right);
-                       Swap (center, right - 1);
-                       return indexes [right - 1];
-               }
-
-               void QuickSort (int left, int right)
-               {
-                       if (left + 3 <= right) {
-                               int l = left, r = right - 1, pivot = MedianOfThree (left, right);
-                               while (true) {
-                                       while (CompareItems (indexes [++l], pivot) < 0) { }
-                                       while (CompareItems (indexes [--r], pivot) > 0) { }
-                                       if (l < r)
-                                               Swap (l, r);
-                                       else
-                                               break;
-                               }
-
-                               // Restore pivot
-                               Swap (l, right - 1);
-                               // Partition and sort
-                               QuickSort (left, l - 1);
-                               QuickSort (l + 1, right);
-                       } else
-                               // If there are three items in the subarray, insertion sort is better
-                               InsertionSort (left, right);
-               }
-
-               void InsertionSort (int left, int right)
-               {
-                       for (int i = left + 1; i <= right; i++) {
-                               int j, tmp = indexes [i];
-
-                               for (j = i; j > left && CompareItems (tmp, indexes [j - 1]) < 0; j--)
-                                       indexes [j] = indexes [j - 1];
+                       if (parent != null)
+                               return parent.CreateContext (context);
 
-                               indexes [j] = tmp;
-                       }
+                       return context;
                }
 
-               void Swap (int left, int right)
+               protected override IEnumerable<TElement> Sort (IEnumerable<TElement> source)
                {
-                       int temp = indexes [right];
-                       indexes [right] = indexes [left];
-                       indexes [left] = temp;
+                       return QuickSort<TElement>.Sort (source, CreateContext (null));
                }
        }
 }
diff --git a/mcs/class/System.Core/System.Linq/QuickSort.cs b/mcs/class/System.Core/System.Linq/QuickSort.cs
new file mode 100644 (file)
index 0000000..f64df40
--- /dev/null
@@ -0,0 +1,144 @@
+//
+// QuickSort.cs
+//
+// Authors:
+//   Alejandro Serrano "Serras" (trupill@yahoo.es)
+//   Marek Safar  <marek.safar@gmail.com>
+//   Jb Evain (jbevain@novell.com)
+//
+// (C) 2007 - 2008 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace System.Linq {
+
+       class QuickSort<TElement> {
+
+               TElement [] elements;
+               int [] indexes;
+               SortContext<TElement> context;
+
+               QuickSort (IEnumerable<TElement> source, SortContext<TElement> context)
+               {
+                       this.elements = source.ToArray ();
+                       this.indexes = CreateIndexes (elements.Length);
+                       this.context = context;
+               }
+
+               static int [] CreateIndexes (int length)
+               {
+                       var indexes = new int [length];
+                       for (int i = 0; i < length; i++)
+                               indexes [i] = i;
+
+                       return indexes;
+               }
+
+               void PerformSort ()
+               {
+                       // If the source contains just zero or one element, there's no need to sort
+                       if (elements.Length <= 1)
+                               return;
+
+                       context.Initialize (elements);
+
+                       // Then sorts the elements according to the collected
+                       // key values and the selected ordering
+                       Sort (0, indexes.Length - 1);
+               }
+
+               int CompareItems (int first_index, int second_index)
+               {
+                       return context.Compare (first_index, second_index);
+               }
+
+               // We look at the first, middle, and last items in the subarray.
+               // Then we put the largest on the right side, the smallest on
+               // the left side, and the median becomes our pivot.
+               int MedianOfThree (int left, int right)
+               {
+                       int center = (left + right) / 2;
+                       if (CompareItems (indexes [center], indexes [left]) < 0)
+                               Swap (left, center);
+                       if (CompareItems (indexes [right], indexes [left]) < 0)
+                               Swap (left, right);
+                       if (CompareItems (indexes [right], indexes [center]) < 0)
+                               Swap (center, right);
+                       Swap (center, right - 1);
+                       return indexes [right - 1];
+               }
+
+               void Sort (int left, int right)
+               {
+                       if (left + 3 <= right) {
+                               int l = left, r = right - 1, pivot = MedianOfThree (left, right);
+                               while (true) {
+                                       while (CompareItems (indexes [++l], pivot) < 0) { }
+                                       while (CompareItems (indexes [--r], pivot) > 0) { }
+                                       if (l < r)
+                                               Swap (l, r);
+                                       else
+                                               break;
+                               }
+
+                               // Restore pivot
+                               Swap (l, right - 1);
+                               // Partition and sort
+                               Sort (left, l - 1);
+                               Sort (l + 1, right);
+                       } else
+                               // If there are three items in the subarray, insertion sort is better
+                               InsertionSort (left, right);
+               }
+
+               void InsertionSort (int left, int right)
+               {
+                       for (int i = left + 1; i <= right; i++) {
+                               int j, tmp = indexes [i];
+
+                               for (j = i; j > left && CompareItems (tmp, indexes [j - 1]) < 0; j--)
+                                       indexes [j] = indexes [j - 1];
+
+                               indexes [j] = tmp;
+                       }
+               }
+
+               void Swap (int left, int right)
+               {
+                       int temp = indexes [right];
+                       indexes [right] = indexes [left];
+                       indexes [left] = temp;
+               }
+
+               public static IEnumerable<TElement> Sort (IEnumerable<TElement> source, SortContext<TElement> context)
+               {
+                       var sorter = new QuickSort<TElement> (source, context);
+
+                       sorter.PerformSort ();
+
+                       for (int i = 0; i < sorter.indexes.Length; i++)
+                               yield return sorter.elements [sorter.indexes [i]];
+               }
+       }
+}
diff --git a/mcs/class/System.Core/System.Linq/SortContext.cs b/mcs/class/System.Core/System.Linq/SortContext.cs
new file mode 100644 (file)
index 0000000..1485117
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// SortContext.cs
+//
+// Author:
+//   Jb Evain (jbevain@novell.com)
+//
+// (C) 2008 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace System.Linq {
+
+       abstract class SortContext<TElement> {
+
+               protected SortDirection direction;
+               protected SortContext<TElement> child_context;
+
+               protected SortContext (SortDirection direction, SortContext<TElement> child_context)
+               {
+                       this.direction = direction;
+                       this.child_context = child_context;
+               }
+
+               public abstract void Initialize (TElement [] elements);
+
+               public abstract int Compare (int first_index, int second_index);
+       }
+}
diff --git a/mcs/class/System.Core/System.Linq/SortDirection.cs b/mcs/class/System.Core/System.Linq/SortDirection.cs
new file mode 100644 (file)
index 0000000..231aa8e
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// SortDirection.cs
+//
+// Author:
+//   Jb Evain (jbevain@novell.com)
+//
+// (C) 2008 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace System.Linq {
+
+       enum SortDirection {
+               Ascending,
+               Descending
+       }
+}
diff --git a/mcs/class/System.Core/System.Linq/SortSequenceContext.cs b/mcs/class/System.Core/System.Linq/SortSequenceContext.cs
new file mode 100644 (file)
index 0000000..67fd2b3
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// SortSequenceContext.cs
+//
+// Author:
+//   Jb Evain (jbevain@novell.com)
+//
+// (C) 2008 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace System.Linq {
+
+       class SortSequenceContext<TElement, TKey> : SortContext<TElement> {
+
+               Func<TElement, TKey> selector;
+               IComparer<TKey> comparer;
+
+               TKey [] keys;
+
+               public SortSequenceContext (Func<TElement, TKey> selector, IComparer<TKey> comparer, SortDirection direction, SortContext<TElement> child_context)
+                       : base (direction, child_context)
+               {
+                       this.selector = selector;
+                       this.comparer = comparer;
+               }
+
+               public override void Initialize (TElement [] elements)
+               {
+                       if (child_context != null)
+                               child_context.Initialize (elements);
+
+                       keys = new TKey [elements.Length];
+                       for (int i = 0; i < keys.Length; i++)
+                               keys [i] = selector (elements [i]);
+               }
+
+               public override int Compare (int first_index, int second_index)
+               {
+                       int comparison = comparer.Compare (keys [first_index], keys [second_index]);
+
+                       if (comparison == 0 && child_context != null)
+                               comparison = child_context.Compare (first_index, second_index);
+
+                       return direction == SortDirection.Descending ? -comparison : comparison;
+               }
+       }
+}