A
download arraysorthelper.cs
Language: C#
Copyright: (c) 2006 Microsoft Corporation. All rights reserved.
LOC: 203
Project Info
Shared Source Common Language Infrastructure(sscli20)
Server: Shared Source Common Language Infrastructure
Type: filesystem
...system\collections\generic\
   arraysorthelper.cs
   comparer.cs
   debugview.cs
   dictionary.cs
   equalitycomparer.cs
   functor.cs
   icollection.cs
   icomparer.cs
   idictionary.cs
   ienumerable.cs
   ienumerator.cs
   iequalitycomparer.cs
   ilist.cs
   keynotfoundexception.cs
   keyvaluepair.cs
   list.cs

// ==++==
// 
//   
//    Copyright (c) 2006 Microsoft Corporation.  All rights reserved.
//   
//    The use and distribution terms for this software are contained in the file
//    named license.txt, which can be found in the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by the
//    terms of this license.
//   
//    You must not remove this notice, or any other, from this software.
//   
// 
// ==--==
/*============================================================
**
** Class:  ArraySortHelper
**
**
** Purpose: class to sort arrays
**
** 
===========================================================*/
namespace System.Collections.Generic {
    
    using System;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    
    [TypeDependencyAttribute("System.Collections.Generic.GenericArraySortHelper`1")]     
    internal class ArraySortHelper<T>  
    {
        static ArraySortHelper<T> defaultArraySortHelper;    
        
        public static ArraySortHelper<T> Default {
            get {
                ArraySortHelper<T> sorter = defaultArraySortHelper;
                if( sorter != null) {
                    return sorter;
                }
                return CreateArraySortHelper();
            }                
        }        
        
        private static ArraySortHelper<T> CreateArraySortHelper() {
            if (typeof(IComparable<T>).IsAssignableFrom(typeof(T))) {  
                defaultArraySortHelper = (ArraySortHelper<T>)(typeof(GenericArraySortHelper<string>).TypeHandle.CreateInstanceForAnotherGenericParameter(typeof(T)));                                                
            }
            else {
                defaultArraySortHelper = new ArraySortHelper<T>();                        
            }
            return defaultArraySortHelper;
        }

        public void Sort(T[] items, int index, int length, IComparer<T> comparer) {
            Sort<Object>(items, (object[])null, index, length, comparer);
        }

        public virtual void Sort<TValue>(T[] keys, TValue[] values, int index, int length, IComparer<T> comparer) {
            BCLDebug.Assert(keys != null, "Check the arguments in the caller!");
            BCLDebug.Assert( index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
            
            if( comparer == null || comparer == Comparer<T>.Default ) {
                comparer = Comparer<T>.Default;
            }

            QuickSort(keys, values, index, index + (length - 1), comparer);
        }

        private void QuickSort<TValue>(T[] keys, TValue[] values, int left, int right, IComparer<T> comparer) {
            do {
                int i = left;
                int j = right;
                T x = keys[i + ((j - i) >> 1)];
                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(Environment.GetResourceString("Arg_BogusIComparer", x, x.GetType().Name, comparer));
                    }
                    catch (Exception e) {
                        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
                    }
                    BCLDebug.Assert(i>=left && j<=right, "(i>=left && j<=right)  Sort failed - Is your IComparer bogus?");
                    if (i > j) break;
                    if (i < j) {
                        T key = keys[i];
                        keys[i] = keys[j];
                        keys[j] = key;
                        if (values != null) {
                            TValue value = values[i];
                            values[i] = values[j];
                            values[j] = value;
                        }
                    }
                    i++;
                    j--;
                } while (i <= j);
                if (j - left <= right - i) {
                    if (left < j) QuickSort(keys, values, left, j, comparer);
                    left = i;
                }
                else {
                    if (i < right) QuickSort(keys, values, i, right, comparer);
                    right = j;
                }
            } while (left < right);
        }

        public virtual int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer) {
            BCLDebug.Assert(array != null, "Check the arguments in the caller!");
            BCLDebug.Assert( index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
            
            if (comparer == null) {
                comparer = System.Collections.Generic.Comparer<T>.Default;
            }

            int lo = index;
            int hi = index + length - 1;
            while (lo <= hi) {
                int i = lo + ((hi -lo) >> 1);
                int order;
                try {
                    order = comparer.Compare(array[i], value);
                }
                catch (Exception e) {
                    throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
                }
                    
                if (order == 0) return i;
                if (order < 0) {
                    lo = i + 1;
                }
                else {
                    hi = i - 1;
                }
            }
            
            return ~lo;            
        }        
    }


    [Serializable()]
    internal class GenericArraySortHelper<T>: ArraySortHelper<T> where T: IComparable<T> {    
        public override int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer) {
            BCLDebug.Assert(array != null, "Check the arguments in the caller!");
            BCLDebug.Assert( index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
            
            if( comparer == null || comparer == Comparer<T>.Default ) {
                return BinarySearch(array, index, length, value);
            }
            else {
                return base.BinarySearch(array, index, length, value, comparer);
            }
        }        
    
        public override void Sort<TValue>(T[] keys, TValue[] values, int index, int length, IComparer<T> comparer) {
            BCLDebug.Assert(keys != null, "Check the arguments in the caller!");
            BCLDebug.Assert( index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
            
            if( comparer == null || comparer == Comparer<T>.Default ) {
                // call the fatser version of QuickSort if the user doesn't provide a comparer
                QuickSort(keys, values, index, index + length -1);
            }
            else {
                base.Sort(keys, values, index, length, comparer);
            }
        }                

        // This function is called when the user doesn't specify any comparer.
        // Since T is constrained here, we can call IComparable<T>.CompareTo here.
        // We can avoid boxing for value type and casting for reference types.
        private int BinarySearch(T[] array, int index, int length, T value) {
            int lo = index;
            int hi = index + length - 1;
            while (lo <= hi) {
                int i = lo + ((hi -lo) >> 1);
                int order;
                try {
                    if( array[i] == null) {
                        order = (value == null) ? 0 : -1;
                    }
                    else {
                        order = array[i].CompareTo(value);
                    }                    
                }
                catch (Exception e) {
                    throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
                }
                    
                if (order == 0) return i;
                if (order < 0) {
                    lo = i + 1;
                }
                else {
                    hi = i - 1;
                }
            }
            
            return ~lo;            
        }

        private void QuickSort<TValue>(T[] keys, TValue[] values, int left, int right) {
             // The code in this function looks very similar to QuickSort in ArraySortHelper<T> class.
             // The difference is that T is constrainted to IComparable<T> here.
             // So the IL code will be different. This function is faster than the one in ArraySortHelper<T>.
            do {
                int i = left;
                int j = right;
                T x = keys[i + ((j - i) >> 1)];
                do {
                    // Add a try block here to detect IComparers (or their
                    // underlying IComparables, etc) that are bogus.
                    try {
                        if( x == null) {
                            // if x null, the loop to find two elements to be switched can be reduced.
                            while (keys[j] != null) j--;                            
                        }
                        else {                            
                            while(x.CompareTo(keys[i]) > 0) i++;
                            while(x.CompareTo(keys[j]) < 0) j--;
                        }                                                                        
                    }
                    catch (IndexOutOfRangeException) {
                        throw new ArgumentException(Environment.GetResourceString("Arg_BogusIComparer", x, x.GetType().Name, null));
                    }
                    catch (Exception e) {
                        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
                    }
                    BCLDebug.Assert(i>=left && j<=right, "(i>=left && j<=right)  Sort failed - Is your IComparer bogus?");
                    if (i > j) break;
                    if (i < j) {
                        T key = keys[i];
                        keys[i] = keys[j];
                        keys[j] = key;
                        if (values != null) {
                            TValue value = values[i];
                            values[i] = values[j];
                            values[j] = value;
                        }                        
                    }
                    i++;
                    j--;
                } while (i <= j);
                if (j - left <= right - i) {
                    if (left < j) QuickSort(keys, values, left, j);
                    left = i;
                }
                else {
                    if (i < right) QuickSort(keys, values, i, right);
                    right = j;
                }
            } while (left < right);
        }                    
    }
}


About Koders | Resources | Downloads | Support | Black Duck | Terms of Service | DMCA | Privacy Policy | Contact Us