forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			145 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
 | 
						|
namespace MonoFN.Cecil {
 | 
						|
	internal sealed class MethodReferenceComparer : EqualityComparer<MethodReference> {
 | 
						|
		// Initialized lazily for each thread
 | 
						|
		[ThreadStatic]
 | 
						|
		static List<MethodReference> xComparisonStack = null;
 | 
						|
 | 
						|
		[ThreadStatic]
 | 
						|
		static List<MethodReference> yComparisonStack = null;
 | 
						|
 | 
						|
		public override bool Equals (MethodReference x, MethodReference y)
 | 
						|
		{
 | 
						|
			return AreEqual (x, y);
 | 
						|
		}
 | 
						|
 | 
						|
		public override int GetHashCode (MethodReference obj)
 | 
						|
		{
 | 
						|
			return GetHashCodeFor (obj);
 | 
						|
		}
 | 
						|
 | 
						|
		public static bool AreEqual (MethodReference x, MethodReference y)
 | 
						|
		{
 | 
						|
			if (ReferenceEquals (x, y))
 | 
						|
				return true;
 | 
						|
 | 
						|
			if (x.HasThis != y.HasThis)
 | 
						|
				return false;
 | 
						|
 | 
						|
			if (x.HasParameters != y.HasParameters)
 | 
						|
				return false;
 | 
						|
 | 
						|
			if (x.HasGenericParameters != y.HasGenericParameters)
 | 
						|
				return false;
 | 
						|
 | 
						|
			if (x.Parameters.Count != y.Parameters.Count)
 | 
						|
				return false;
 | 
						|
 | 
						|
			if (x.Name != y.Name)
 | 
						|
				return false;
 | 
						|
 | 
						|
			if (!TypeReferenceEqualityComparer.AreEqual (x.DeclaringType, y.DeclaringType))
 | 
						|
				return false;
 | 
						|
 | 
						|
			var xGeneric = x as GenericInstanceMethod;
 | 
						|
			var yGeneric = y as GenericInstanceMethod;
 | 
						|
			if (xGeneric != null || yGeneric != null) {
 | 
						|
				if (xGeneric == null || yGeneric == null)
 | 
						|
					return false;
 | 
						|
 | 
						|
				if (xGeneric.GenericArguments.Count != yGeneric.GenericArguments.Count)
 | 
						|
					return false;
 | 
						|
 | 
						|
				for (int i = 0; i < xGeneric.GenericArguments.Count; i++)
 | 
						|
					if (!TypeReferenceEqualityComparer.AreEqual (xGeneric.GenericArguments [i], yGeneric.GenericArguments [i]))
 | 
						|
						return false;
 | 
						|
			}
 | 
						|
 | 
						|
			var xResolved = x.Resolve ();
 | 
						|
			var yResolved = y.Resolve ();
 | 
						|
 | 
						|
			if (xResolved != yResolved)
 | 
						|
				return false;
 | 
						|
 | 
						|
			if (xResolved == null) {
 | 
						|
				// We couldn't resolve either method. In order for them to be equal, their parameter types _must_ match. But wait, there's a twist!
 | 
						|
				// There exists a situation where we might get into a recursive state: parameter type comparison might lead to comparing the same
 | 
						|
				// methods again if the parameter types are generic parameters whose owners are these methods. We guard against these by using a
 | 
						|
				// thread static list of all our comparisons carried out in the stack so far, and if we're in progress of comparing them already,
 | 
						|
				// we'll just say that they match.
 | 
						|
 | 
						|
				if (xComparisonStack == null)
 | 
						|
					xComparisonStack = new List<MethodReference> ();
 | 
						|
 | 
						|
				if (yComparisonStack == null)
 | 
						|
					yComparisonStack = new List<MethodReference> ();
 | 
						|
 | 
						|
				for (int i = 0; i < xComparisonStack.Count; i++) {
 | 
						|
					if (xComparisonStack [i] == x && yComparisonStack [i] == y)
 | 
						|
						return true;
 | 
						|
				}
 | 
						|
 | 
						|
				xComparisonStack.Add (x);
 | 
						|
 | 
						|
				try {
 | 
						|
					yComparisonStack.Add (y);
 | 
						|
 | 
						|
					try {
 | 
						|
						for (int i = 0; i < x.Parameters.Count; i++) {
 | 
						|
							if (!TypeReferenceEqualityComparer.AreEqual (x.Parameters [i].ParameterType, y.Parameters [i].ParameterType))
 | 
						|
								return false;
 | 
						|
						}
 | 
						|
					}
 | 
						|
					finally {
 | 
						|
						yComparisonStack.RemoveAt (yComparisonStack.Count - 1);
 | 
						|
					}
 | 
						|
				}
 | 
						|
				finally {
 | 
						|
					xComparisonStack.RemoveAt (xComparisonStack.Count - 1);
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		public static bool AreSignaturesEqual (MethodReference x, MethodReference y, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact)
 | 
						|
		{
 | 
						|
			if (x.HasThis != y.HasThis)
 | 
						|
				return false;
 | 
						|
 | 
						|
			if (x.Parameters.Count != y.Parameters.Count)
 | 
						|
				return false;
 | 
						|
 | 
						|
			if (x.GenericParameters.Count != y.GenericParameters.Count)
 | 
						|
				return false;
 | 
						|
 | 
						|
			for (var i = 0; i < x.Parameters.Count; i++)
 | 
						|
				if (!TypeReferenceEqualityComparer.AreEqual (x.Parameters [i].ParameterType, y.Parameters [i].ParameterType, comparisonMode))
 | 
						|
					return false;
 | 
						|
 | 
						|
			if (!TypeReferenceEqualityComparer.AreEqual (x.ReturnType, y.ReturnType, comparisonMode))
 | 
						|
				return false;
 | 
						|
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		public static int GetHashCodeFor (MethodReference obj)
 | 
						|
		{
 | 
						|
			// a very good prime number
 | 
						|
			const int hashCodeMultiplier = 486187739;
 | 
						|
 | 
						|
			var genericInstanceMethod = obj as GenericInstanceMethod;
 | 
						|
			if (genericInstanceMethod != null) {
 | 
						|
				var hashCode = GetHashCodeFor (genericInstanceMethod.ElementMethod);
 | 
						|
				for (var i = 0; i < genericInstanceMethod.GenericArguments.Count; i++)
 | 
						|
					hashCode = hashCode * hashCodeMultiplier + TypeReferenceEqualityComparer.GetHashCodeFor (genericInstanceMethod.GenericArguments [i]);
 | 
						|
				return hashCode;
 | 
						|
			}
 | 
						|
 | 
						|
			return TypeReferenceEqualityComparer.GetHashCodeFor (obj.DeclaringType) * hashCodeMultiplier + obj.Name.GetHashCode ();
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |