[Add] FishNet
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MonoFN.Cecil
|
||||
{
|
||||
internal sealed class MethodReferenceComparer : EqualityComparer<MethodReference>
|
||||
{
|
||||
// Initialized lazily for each thread
|
||||
[ThreadStatic]
|
||||
private static List<MethodReference> xComparisonStack = null;
|
||||
[ThreadStatic]
|
||||
private 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;
|
||||
|
||||
GenericInstanceMethod xGeneric = x as GenericInstanceMethod;
|
||||
GenericInstanceMethod 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;
|
||||
}
|
||||
|
||||
MethodDefinition xResolved = x.Resolve();
|
||||
MethodDefinition 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();
|
||||
|
||||
if (yComparisonStack == null)
|
||||
yComparisonStack = new();
|
||||
|
||||
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 (int 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;
|
||||
|
||||
GenericInstanceMethod genericInstanceMethod = obj as GenericInstanceMethod;
|
||||
if (genericInstanceMethod != null)
|
||||
{
|
||||
int hashCode = GetHashCodeFor(genericInstanceMethod.ElementMethod);
|
||||
for (int 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user