|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace System.Windows.Forms.Layout;
internal partial class TableLayout
{
// Private value type used by the Sort methods.
private readonly struct SorterObjectArray
{
private readonly LayoutInfo[] _keys;
private readonly IComparer<LayoutInfo> _comparer;
internal SorterObjectArray(LayoutInfo[] keys, IComparer<LayoutInfo> comparer)
{
comparer ??= Comparer<LayoutInfo>.Default;
_keys = keys;
_comparer = comparer;
}
internal readonly void SwapIfGreaterWithItems(int a, int b)
{
if (a != b)
{
try
{
if (_comparer.Compare(_keys[a], _keys[b]) > 0)
{
(_keys[a], _keys[b]) = (_keys[b], _keys[a]);
}
}
catch (IndexOutOfRangeException)
{
throw new ArgumentException();
}
catch (Exception)
{
throw new InvalidOperationException();
}
}
}
internal void QuickSort(int left, int right)
{
// Can use the much faster jit helpers for array access.
do
{
int i = left;
int j = right;
// pre-sort the low, middle (pivot), and high values in place.
// this improves performance in the face of already sorted data, or
// data that is made up of multiple sorted runs appended together.
int middle = GetMedian(i, j);
SwapIfGreaterWithItems(i, middle); // swap the low with the mid point
SwapIfGreaterWithItems(i, j); // swap the low with the high
SwapIfGreaterWithItems(middle, j); // swap the middle with the high
LayoutInfo x = _keys[middle];
do
{
// Add a try block here to detect IComparers (or their
// underlying IComparables, etc) that are bogus.
try
{
while (_comparer.Compare(_keys[i], x) < 0)
{
i++;
}
while (_comparer.Compare(x, _keys[j]) < 0)
{
j--;
}
}
catch (IndexOutOfRangeException)
{
throw new ArgumentException();
}
catch (Exception)
{
throw new InvalidOperationException();
}
if (i > j)
{
break;
}
if (i < j)
{
(_keys[i], _keys[j]) = (_keys[j], _keys[i]);
}
i++;
j--;
}
while (i <= j);
if (j - left <= right - i)
{
if (left < j)
{
QuickSort(left, j);
}
left = i;
}
else
{
if (i < right)
{
QuickSort(i, right);
}
right = j;
}
}
while (left < right);
}
}
}
|