[corlib] Generic comparers from reference sources
authorMarek Safar <marek.safar@gmail.com>
Thu, 9 Apr 2015 12:26:05 +0000 (14:26 +0200)
committerMarek Safar <marek.safar@gmail.com>
Thu, 9 Apr 2015 12:26:43 +0000 (14:26 +0200)
external/referencesource
mcs/class/corlib/ReferenceSources/JitHelpers.cs
mcs/class/corlib/ReferenceSources/RuntimeType.cs
mcs/class/corlib/System.Collections.Generic/Comparer.cs [deleted file]
mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs [deleted file]
mcs/class/corlib/System/Array.cs
mcs/class/corlib/System/Buffer.cs
mcs/class/corlib/Test/System.Collections.Generic/EqualityComparerTest.cs
mcs/class/corlib/corlib.dll.sources

index 7d6aea73bb44fa0e3fa51221106571b51a3425e5..e8b48b775c0b796f424d3d4e5375c6ff2dc21542 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7d6aea73bb44fa0e3fa51221106571b51a3425e5
+Subproject commit e8b48b775c0b796f424d3d4e5375c6ff2dc21542
index 05c4d716cc118fafadbf26fdb732f3b1adee7af7..d5d822fdb00e9c4ddcd788046f1b0918b3aa5409 100644 (file)
@@ -6,7 +6,17 @@ namespace System.Runtime.CompilerServices {
        {
                static internal T UnsafeCast<T>(Object o) where T : class
                {
-                       return (T)o;
+                       return Array.UnsafeMov<object, T> (o);
+               }
+
+               static internal int UnsafeEnumCast<T>(T val) where T : struct
+               {
+                       return Array.UnsafeMov<T, int> (val);
+               }
+
+               static internal long UnsafeEnumCastLong<T>(T val) where T : struct
+               {
+                       throw new NotImplementedException ();
                }
        }
 }
\ No newline at end of file
index a2673c348866c13732e8bb43d50474d217519693..9dd5e9c6ad01f26df1b5969a36a3bf17e0bb9f21 100644 (file)
@@ -394,6 +394,13 @@ namespace System
                        return constraints;
                }
 
+               internal static object CreateInstanceForAnotherGenericParameter (Type genericType, RuntimeType genericArgument)
+               {
+                       var gt = (RuntimeType) MakeGenericType (genericType, new Type [] { genericArgument });
+                       var ctor = gt.GetDefaultConstructor ();
+                       return ctor.InternalInvoke (null, null);
+               }
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                static extern Type MakeGenericType (Type gt, Type [] types);
 
diff --git a/mcs/class/corlib/System.Collections.Generic/Comparer.cs b/mcs/class/corlib/System.Collections.Generic/Comparer.cs
deleted file mode 100644 (file)
index d19ce2c..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-//
-// Comparer.cs
-//
-// Authors:
-//     Ben Maurer (bmaurer@ximian.com)
-//     Marek Safar (marek.safar@gmail.com)
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.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.Runtime.InteropServices;
-
-namespace System.Collections.Generic {
-       [Serializable]
-       public abstract class Comparer<T> : IComparer<T>, IComparer
-       {
-               static readonly Comparer <T> _default = typeof (IComparable<T>).IsAssignableFrom (typeof (T)) ?
-                       (Comparer<T>) Activator.CreateInstance (typeof (GenericComparer <>).MakeGenericType (typeof (T))) :
-                       new DefaultComparer ();
-               
-               public abstract int Compare (T x, T y);
-       
-               public static Comparer<T> Default {
-                       get {
-                               return _default;
-                       }
-               }
-
-               public static Comparer<T> Create (Comparison<T> comparison)
-               {
-                       if (comparison == null)
-                               throw new ArgumentNullException ("comparison");
-
-                       return new ComparisonComparer<T> (comparison);
-               }
-
-               int IComparer.Compare (object x, object y)
-               {
-                       if (x == y)
-                               return 0;
-                       if (x == null)
-                               return y == null ? 0 : -1;
-                       if (y == null)
-                               return 1;
-                       
-                       if (x is T && y is T)
-                               return Compare ((T) x, (T) y);
-                       
-                       throw new ArgumentException ();
-               }
-       
-               [Serializable]
-               sealed class DefaultComparer : Comparer<T>
-               {
-                       public override int Compare (T x, T y)
-                       {
-                               // `null' is less than any other ref type
-                               if (x == null)
-                                       return y == null ? 0 : -1;
-                               if (y == null)
-                                       return 1;
-       
-                               var i = x as IComparable;
-                               if (i != null)
-                                       return i.CompareTo (y);
-
-                               i = y as IComparable;
-                               if (i != null)
-                                       return -i.CompareTo (x);
-
-                               throw new ArgumentException ("At least one argument has to implement IComparable interface");
-                       }
-               }
-       }
-       
-       [Serializable]
-       sealed class GenericComparer<T> : Comparer<T> where T : IComparable<T>
-       {
-               public override int Compare (T x, T y)
-               {
-                       // `null' is less than any other ref type
-                       if (x == null)
-                               return y == null ? 0 : -1;
-                       if (y == null)
-                               return 1;
-                       
-                       return x.CompareTo (y);
-               }
-       }
-       [Serializable]
-       sealed class ComparisonComparer<T> : Comparer<T>
-       {
-               readonly Comparison<T> comparison;
-
-               public ComparisonComparer (Comparison<T> comparison)
-               {
-                       this.comparison = comparison;
-               }
-
-               public override int Compare (T x, T y)
-               {
-                       return comparison (x, y);
-               }
-       }
-}
diff --git a/mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs b/mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs
deleted file mode 100644 (file)
index 9338f96..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-//
-// EqualityComparer.cs
-//
-// Authors:
-//     Ben Maurer (bmaurer@ximian.com)
-//     Marek Safar (marek.safar@gmail.com)
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.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.Runtime.InteropServices;
-
-namespace System.Collections.Generic {
-       [Serializable]
-       public abstract class EqualityComparer <T> : IEqualityComparer, IEqualityComparer <T> {
-               
-               static EqualityComparer ()
-               {
-                       var t = typeof (T);
-                       if (t == typeof (string)) {
-                               _default = (EqualityComparer<T>) (object) new InternalStringComparer ();
-                               return;
-                       }
-
-                       if (t == typeof (int)) {
-                               _default = (EqualityComparer<T>) (object) new IntEqualityComparer ();
-                               return;
-                       }
-
-                       if (t.IsEnum && Enum.GetUnderlyingType (t) == typeof (int)) {
-                               _default = new EnumIntEqualityComparer<T> ();
-                               return;
-                       }
-
-                       if (typeof (IEquatable <T>).IsAssignableFrom (t))
-                               _default = (EqualityComparer <T>) Activator.CreateInstance (typeof (GenericEqualityComparer <>).MakeGenericType (t));
-                       else
-                               _default = new DefaultComparer<T> ();
-               }
-               
-               public abstract int GetHashCode (T obj);
-               public abstract bool Equals (T x, T y);
-       
-               static readonly EqualityComparer <T> _default;
-               
-               public static EqualityComparer <T> Default {
-                       get {
-                               return _default;
-                       }
-               }
-
-               int IEqualityComparer.GetHashCode (object obj)
-               {
-                       if (obj == null)
-                               return 0;
-
-                       if (!(obj is T))
-                               throw new ArgumentException ("Argument is not compatible", "obj");
-
-                       return GetHashCode ((T)obj);
-               }
-
-               bool IEqualityComparer.Equals (object x, object y)
-               {
-                       if (x == y)
-                               return true;
-
-                       if (x == null || y == null)
-                               return false;
-
-                       if (!(x is T))
-                               throw new ArgumentException ("Argument is not compatible", "x");
-                       if (!(y is T))
-                               throw new ArgumentException ("Argument is not compatible", "y");
-                       return Equals ((T)x, (T)y);
-               }
-               
-               internal virtual int IndexOf (T[] array, T value, int startIndex, int endIndex)
-               {
-                       for (int i = startIndex; i < endIndex; ++i) {
-                               if (Equals (Array.UnsafeLoad (array, i), value))
-                                       return i;
-                       }
-
-                       return -1;
-               }
-       }
-
-       [Serializable]
-       sealed class DefaultComparer<T> : EqualityComparer<T> {
-       
-               public override int GetHashCode (T obj)
-               {
-                       if (obj == null)
-                               return 0;
-                       return obj.GetHashCode ();
-               }
-       
-               public override bool Equals (T x, T y)
-               {
-                       if (x == null)
-                               return y == null;
-
-                       return x.Equals (y);
-               }
-       }
-
-       [Serializable]
-       sealed class InternalStringComparer : EqualityComparer<string> {
-       
-               public override int GetHashCode (string obj)
-               {
-                       if (obj == null)
-                               return 0;
-                       return obj.GetHashCode ();
-               }
-       
-               public override bool Equals (string x, string y)
-               {
-                       if (x == null)
-                               return y == null;
-
-                       if ((object) x == (object) y)
-                               return true;
-                               
-                       return x.Equals (y);
-               }
-
-               internal override int IndexOf (string[] array, string value, int startIndex, int endIndex)
-               {
-                       for (int i = startIndex; i < endIndex; ++i) {
-                               if (Array.UnsafeLoad (array, i) == value)
-                                       return i;
-                       }
-
-                       return -1;
-               }
-       }
-
-       [Serializable]
-       sealed class IntEqualityComparer : EqualityComparer<int>
-       {
-               public override int GetHashCode (int obj)
-               {
-                       return obj;
-               }
-
-               public override bool Equals (int x, int y)
-               {
-                       return x == y;
-               }
-
-               internal override int IndexOf (int[] array, int value, int startIndex, int endIndex)
-               {
-                       for (int i = startIndex; i < endIndex; ++i) {
-                               if (Array.UnsafeLoad (array, i) == value)
-                                       return i;
-                       }
-
-                       return -1;
-               }
-       }
-
-       [Serializable]
-       sealed class EnumIntEqualityComparer<T> : EqualityComparer<T>
-       {
-               public override int GetHashCode (T obj)
-               {
-                       return Array.UnsafeMov<T, int> (obj);
-               }
-
-               public override bool Equals (T x, T y)
-               {
-                       return Array.UnsafeMov<T, int> (x) == Array.UnsafeMov<T, int> (y);
-               }
-
-               internal override int IndexOf (T[] array, T value, int startIndex, int endIndex)
-               {
-                       int v = Array.UnsafeMov<T, int> (value);
-                       var a = Array.UnsafeMov<T[], int[]> (array);
-                       for (int i = startIndex; i < endIndex; ++i) {
-                               if (Array.UnsafeLoad (a, i) == v)
-                                       return i;
-                       }
-
-                       return -1;
-               }
-       }
-
-       [Serializable]
-       sealed class GenericEqualityComparer <T> : EqualityComparer <T> where T : IEquatable <T> {
-
-               public override int GetHashCode (T obj)
-               {
-                       if (obj == null)
-                               return 0;
-                       return obj.GetHashCode ();
-               }
-
-               public override bool Equals (T x, T y)
-               {
-                       if (x == null)
-                               return y == null;
-                       
-                       return x.Equals (y);
-               }
-       }
-}
index b4afbe2eb84bd10203be62dc732b40647bd43a0f..9c263400572cc9681d3fba5d8ad1ce6f5c579a1c 100644 (file)
@@ -3045,7 +3045,7 @@ namespace System
                        if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
                                throw new ArgumentOutOfRangeException ();
 
-                       return EqualityComparer<T>.Default.IndexOf (array, value, startIndex, startIndex + count);
+                       return EqualityComparer<T>.Default.IndexOf (array, value, startIndex, count);
                }
                
                public static int LastIndexOf<T> (T [] array, T value)
index 3f4960d7b79bed69fede30282906e029c79a89a0..3c20630fcf37a38fabc00132d45657d2a1a96cfb 100644 (file)
@@ -260,5 +260,77 @@ namespace System {
                        }
                        memcpy4 (dest, src, size);
                }
+
+        internal unsafe static int IndexOfByte(byte* src, byte value, int index, int count)
+        {
+            Contract.Assert(src != null, "src should not be null");
+
+            byte* pByte = src + index;
+
+            // Align up the pointer to sizeof(int).
+            while (((int)pByte & 3) != 0)
+            {
+                if (count == 0)
+                    return -1;
+                else if (*pByte == value)
+                    return (int) (pByte - src);
+
+                count--;
+                pByte++;
+            }
+
+            // Fill comparer with value byte for comparisons
+            //
+            // comparer = 0/0/value/value
+            uint comparer = (((uint)value << 8) + (uint)value);
+            // comparer = value/value/value/value
+            comparer = (comparer << 16) + comparer;
+
+            // Run through buffer until we hit a 4-byte section which contains
+            // the byte we're looking for or until we exhaust the buffer.
+            while (count > 3)
+            {
+                // Test the buffer for presence of value. comparer contains the byte
+                // replicated 4 times.
+                uint t1 = *(uint*)pByte;
+                t1 = t1 ^ comparer;
+                uint t2 = 0x7efefeff + t1;
+                t1 = t1 ^ 0xffffffff;
+                t1 = t1 ^ t2;
+                t1 = t1 & 0x81010100;
+
+                // if t1 is zero then these 4-bytes don't contain a match
+                if (t1 != 0)
+                {
+                    // We've found a match for value, figure out which position it's in.
+                    int foundIndex = (int) (pByte - src);
+                    if (pByte[0] == value)
+                        return foundIndex;
+                    else if (pByte[1] == value)
+                        return foundIndex + 1;
+                    else if (pByte[2] == value)
+                        return foundIndex + 2;
+                    else if (pByte[3] == value)
+                        return foundIndex + 3;
+                }
+
+                count -= 4;
+                pByte += 4;
+
+            }
+
+            // Catch any bytes that might be left at the tail of the buffer
+            while (count > 0)
+            {
+                if (*pByte == value)
+                    return (int) (pByte - src);
+
+                count--;
+                pByte++;
+            }
+
+            // If we don't have a match return -1;
+            return -1;
+        }              
        }
 }
index 5a0fd3b6a253da373385e2652435f3db626a6e8a..e238781bcb73f4cce4f887eb2c9bc9ef37bda514 100644 (file)
@@ -37,6 +37,11 @@ namespace MonoTests.System.Collections.Generic {
 
        [TestFixture]
        public class EqualityComparerTest {
+               enum E
+               {
+                       A,
+                       B
+               }
 
                [Test]
                public void Default_GetHashCode_Null ()
@@ -59,6 +64,13 @@ namespace MonoTests.System.Collections.Generic {
                        IEqualityComparer comparer = EqualityComparer<object>.Default;
                        Assert.IsTrue (comparer.Equals (null, null));
                }
+
+               [Test]
+               public void EnumComparison ()
+               {
+                       Assert.IsFalse (EqualityComparer<E>.Default.Equals (E.A, E.B));
+                       Assert.IsFalse (EqualityComparer<object>.Default.Equals (E.A, E.B));
+               }
        }
 }
 
index 4aef1fb9ff7dc0415da6ed70f256dd51a555b790..1a27579a1572dfd3a33886f95f1e063fee91677d 100644 (file)
@@ -1100,8 +1100,6 @@ System.Threading/Timer.cs
 System.Threading/TimerCallback.cs
 System.Threading/Volatile.cs
 System.Threading/WaitHandle.cs
-System.Collections.Generic/Comparer.cs
-System.Collections.Generic/EqualityComparer.cs
 
 System.Threading.Tasks/DecoupledTask.cs
 ../Mono.Parallel/Mono.Threading/AtomicBoolean.cs
@@ -1307,8 +1305,10 @@ ReferenceSources/TypeBuilderInstantiation.cs
 ../../../external/referencesource/mscorlib/system/collections/stack.cs
 ../../../external/referencesource/mscorlib/system/collections/structuralcomparisons.cs
 
+../../../external/referencesource/mscorlib/system/collections/generic/comparer.cs
 ../../../external/referencesource/mscorlib/system/collections/generic/debugview.cs
 ../../../external/referencesource/mscorlib/system/collections/generic/dictionary.cs
+../../../external/referencesource/mscorlib/system/collections/generic/equalitycomparer.cs
 ../../../external/referencesource/mscorlib/system/collections/generic/icollection.cs
 ../../../external/referencesource/mscorlib/system/collections/generic/icomparer.cs
 ../../../external/referencesource/mscorlib/system/collections/generic/idictionary.cs