Skip to content

Commit 9d191fc

Browse files
committed
Implemented faster string search.
1 parent f30748f commit 9d191fc

File tree

1 file changed

+70
-8
lines changed

1 file changed

+70
-8
lines changed

ReClass.NET/MemoryScanner/Comparer/StringMemoryComparer.cs

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using System.Diagnostics;
1+
using System.Diagnostics;
32
using System.Linq;
43
using System.Text;
54

@@ -8,24 +7,87 @@ namespace ReClassNET.MemoryScanner.Comparer
87
public class StringMemoryComparer : IScanComparer
98
{
109
public ScanCompareType CompareType => ScanCompareType.Equal;
11-
public bool CaseSensitive { get; }
10+
public bool IsCaseSensitive { get; }
1211
public Encoding Encoding { get; }
1312
public string Value { get; }
1413
public char[] Chars { get; }
1514
public int ValueSize { get; }
1615

17-
public StringMemoryComparer(string value, Encoding encoding, bool caseSensitive)
16+
private unsafe delegate char GetCharacter(byte* data, int index);
17+
18+
private readonly GetCharacter getCharacter;
19+
20+
public StringMemoryComparer(string value, Encoding encoding, bool isCaseSensitive)
1821
{
19-
CaseSensitive = caseSensitive;
22+
IsCaseSensitive = isCaseSensitive;
2023
Encoding = encoding;
2124
Value = value;
22-
Chars = value.Select(c => caseSensitive ? c : char.ToUpperInvariant(c)).ToArray();
23-
ValueSize = encoding.GetByteCount(value);
25+
Chars = value.Select(c => isCaseSensitive ? c : char.ToUpperInvariant(c)).ToArray();
26+
ValueSize = Encoding.GetByteCount(value);
27+
28+
unsafe
29+
{
30+
getCharacter = Encoding == Encoding.UTF8
31+
? IsCaseSensitive
32+
? (GetCharacter)GetCharacterCaseSensitiveUtf8
33+
: GetCharacterCaseInsensitiveUtf8
34+
: Encoding == Encoding.Unicode
35+
? IsCaseSensitive
36+
? (GetCharacter)GetCharacterCaseSensitiveUtf16
37+
: GetCharacterCaseInsensitiveUtf16
38+
: IsCaseSensitive
39+
? (GetCharacter)GetCharacterCaseSensitiveUtf32
40+
: GetCharacterCaseInsensitiveUtf32;
41+
}
42+
}
43+
44+
private static unsafe char GetCharacterCaseSensitiveUtf8(byte* data, int index)
45+
{
46+
return (char)*(data + index);
47+
}
48+
49+
private static unsafe char GetCharacterCaseInsensitiveUtf8(byte* data, int index)
50+
{
51+
return char.ToUpperInvariant(GetCharacterCaseSensitiveUtf8(data, index));
52+
}
53+
54+
private static unsafe char GetCharacterCaseSensitiveUtf16(byte* data, int index)
55+
{
56+
return *((char*)data + index);
57+
}
58+
59+
private static unsafe char GetCharacterCaseInsensitiveUtf16(byte* data, int index)
60+
{
61+
return char.ToUpperInvariant(GetCharacterCaseSensitiveUtf16(data, index));
62+
}
63+
64+
private static unsafe char GetCharacterCaseSensitiveUtf32(byte* data, int index)
65+
{
66+
var dst = stackalloc char[1];
67+
Encoding.UTF32.GetChars(data + index * sizeof(int), 4, dst, 1);
68+
return *dst;
69+
}
70+
71+
private static unsafe char GetCharacterCaseInsensitiveUtf32(byte* data, int index)
72+
{
73+
return char.ToUpperInvariant(GetCharacterCaseSensitiveUtf32(data, index));
2474
}
2575

2676
public unsafe bool Compare(byte* data, out ScanResult result)
2777
{
28-
throw new NotImplementedException();
78+
result = null;
79+
80+
for (var i = 0; i < Chars.Length; ++i)
81+
{
82+
if (Chars[i] != getCharacter(data, i))
83+
{
84+
return false;
85+
}
86+
}
87+
88+
result = new StringScanResult(Value, Encoding);
89+
90+
return true;
2991
}
3092

3193
public unsafe bool Compare(byte* data, ScanResult previous, out ScanResult result)

0 commit comments

Comments
 (0)