Repository navigation
Expand file tree
/
Copy pathDoubleMemoryComparer.cs
More file actions
122 lines (104 loc) · 3.94 KB
/
Copy pathDoubleMemoryComparer.cs
File metadata and controls
122 lines (104 loc) · 3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
using System;
using System.Diagnostics;
using ReClassNET.Extensions;
using ReClassNET.Util.Conversion;
namespace ReClassNET.MemoryScanner.Comparer
{
public class DoubleMemoryComparer : ISimpleScanComparer
{
public ScanCompareType CompareType { get; }
public ScanRoundMode RoundType { get; }
public double Value1 { get; }
public double Value2 { get; }
public int ValueSize => sizeof(double);
private readonly int significantDigits;
private readonly double minValue;
private readonly double maxValue;
private readonly EndianBitConverter bitConverter;
public DoubleMemoryComparer(ScanCompareType compareType, ScanRoundMode roundType, int significantDigits, double value1, double value2, EndianBitConverter bitConverter)
{
CompareType = compareType;
RoundType = roundType;
this.significantDigits = Math.Max(significantDigits, 1);
Value1 = Math.Round(value1, this.significantDigits, MidpointRounding.AwayFromZero);
Value2 = Math.Round(value2, this.significantDigits, MidpointRounding.AwayFromZero);
var factor = (int)Math.Pow(10.0, this.significantDigits);
minValue = value1 - 1.0 / factor;
maxValue = value1 + 1.0 / factor;
this.bitConverter = bitConverter;
}
private bool CheckRoundedEquality(double value) =>
RoundType switch
{
ScanRoundMode.Strict => Value1.IsNearlyEqual(Math.Round(value, significantDigits, MidpointRounding.AwayFromZero), 0.0001),
ScanRoundMode.Normal => minValue < value && value < maxValue,
ScanRoundMode.Truncate => (long)value == (long)Value1,
_ => throw new ArgumentOutOfRangeException()
};
public bool Compare(byte[] data, int index, out ScanResult result)
{
return CompareInternal(
data,
index,
value => CompareType switch
{
ScanCompareType.Equal => CheckRoundedEquality(value),
ScanCompareType.NotEqual => !CheckRoundedEquality(value),
ScanCompareType.GreaterThan => value > Value1,
ScanCompareType.GreaterThanOrEqual => value >= Value1,
ScanCompareType.LessThan => value < Value1,
ScanCompareType.LessThanOrEqual => value <= Value1,
ScanCompareType.Between => Value1 < value && value < Value2,
ScanCompareType.BetweenOrEqual => Value1 <= value && value <= Value2,
ScanCompareType.Unknown => true,
_ => throw new InvalidCompareTypeException(CompareType)
},
out result
);
}
public bool Compare(byte[] data, int index, ScanResult previous, out ScanResult result)
{
#if DEBUG
Debug.Assert(previous is DoubleScanResult);
#endif
return Compare(data, index, (DoubleScanResult)previous, out result);
}
public bool Compare(byte[] data, int index, DoubleScanResult previous, out ScanResult result)
{
return CompareInternal(
data,
index,
value => CompareType switch
{
ScanCompareType.Equal => CheckRoundedEquality(value),
ScanCompareType.NotEqual => !CheckRoundedEquality(value),
ScanCompareType.Changed => value != previous.Value,
ScanCompareType.NotChanged => value == previous.Value,
ScanCompareType.GreaterThan => value > Value1,
ScanCompareType.GreaterThanOrEqual => value >= Value1,
ScanCompareType.Increased => value > previous.Value,
ScanCompareType.IncreasedOrEqual => value >= previous.Value,
ScanCompareType.LessThan => value < Value1,
ScanCompareType.LessThanOrEqual => value <= Value1,
ScanCompareType.Decreased => value < previous.Value,
ScanCompareType.DecreasedOrEqual => value <= previous.Value,
ScanCompareType.Between => Value1 < value && value < Value2,
ScanCompareType.BetweenOrEqual => Value1 <= value && value <= Value2,
_ => throw new InvalidCompareTypeException(CompareType)
},
out result
);
}
private bool CompareInternal(byte[] data, int index, Func<double, bool> matcher, out ScanResult result)
{
result = null;
var value = bitConverter.ToDouble(data, index);
if (!matcher(value))
{
return false;
}
result = new DoubleScanResult(value);
return true;
}
}
}