Skip to content

Commit

Permalink
Constexpr find_pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
ZeroMemes committed Dec 13, 2022
1 parent 3fc7f8c commit e9409e6
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 47 deletions.
6 changes: 6 additions & 0 deletions include/libhat/Defines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@
#define LIBHAT_BLSR64(num) num & (num - 1)
#endif
#endif

#if __cpp_if_consteval >= 202106L
#define LIBHAT_IF_CONSTEVAL consteval
#else
#define LIBHAT_IF_CONSTEVAL (std::is_constant_evaluated())
#endif
15 changes: 0 additions & 15 deletions include/libhat/ScanMode.hpp

This file was deleted.

52 changes: 50 additions & 2 deletions include/libhat/Scanner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

#include <algorithm>
#include <array>
#include <execution>
#include <utility>

#include "Defines.hpp"
#include "Process.hpp"
#include "Signature.hpp"

Expand Down Expand Up @@ -47,6 +49,46 @@ namespace hat {
std::byte* result;
};

namespace detail {

enum class scan_mode {
Auto,
Search,
FastFirst,
AVX2,
AVX512,
Neon
};

template<scan_mode>
scan_result find_pattern(std::byte* begin, std::byte* end, signature_view signature);

template<>
scan_result find_pattern<scan_mode::Auto>(std::byte* begin, std::byte* end, signature_view signature);

template<>
constexpr scan_result find_pattern<scan_mode::FastFirst>(std::byte* begin, std::byte* end, signature_view signature) {
const auto firstByte = *signature[0];
const auto scanEnd = end - signature.size() + 1;

for (auto i = begin; i != scanEnd; i++) {
// Use std::find to efficiently find the first byte
i = std::find(std::execution::unseq, i, scanEnd, firstByte);
if (i == scanEnd) {
break;
}
// Compare everything after the first byte
auto match = std::equal(signature.begin() + 1, signature.end(), i + 1, [](auto opt, auto byte) {
return !opt.has_value() || *opt == byte;
});
if (match) {
return i;
}
}
return nullptr;
}
}

enum class compiler_type {
MSVC,
MinGW
Expand All @@ -73,9 +115,15 @@ namespace hat {
);

/// Root implementation of FindPattern
scan_result find_pattern(
constexpr scan_result find_pattern(
std::byte* begin,
std::byte* end,
signature_view signature
);
) {
if LIBHAT_IF_CONSTEVAL {
return detail::find_pattern<detail::scan_mode::FastFirst>(begin, end, signature);
} else {
return detail::find_pattern<detail::scan_mode::Auto>(begin, end, signature);
}
}
}
28 changes: 4 additions & 24 deletions src/Scanner.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#include <libhat/Scanner.hpp>

#include <map>
#include <execution>

#include <libhat/Defines.hpp>
#include <libhat/System.hpp>
#include <libhat/ScanMode.hpp>

namespace hat {

Expand Down Expand Up @@ -90,6 +88,9 @@ namespace hat {
}
return find_pattern(std::to_address(data.begin()), std::to_address(data.end()), signature);
}
}

namespace hat::detail {

template<>
[[deprecated]] scan_result find_pattern<scan_mode::Search>(std::byte* begin, std::byte* end, signature_view signature) {
Expand All @@ -103,28 +104,7 @@ namespace hat {
}

template<>
scan_result find_pattern<scan_mode::FastFirst>(std::byte* begin, std::byte* end, signature_view signature) {
const auto firstByte = *signature[0];
const auto scanEnd = end - signature.size() + 1;

for (auto i = begin; i != scanEnd; i++) {
// Use std::find to efficiently find the first byte
i = std::find(std::execution::unseq, i, scanEnd, firstByte);
if (i == scanEnd) {
break;
}
// Compare everything after the first byte
auto match = std::equal(signature.begin() + 1, signature.end(), i + 1, [](auto opt, auto byte) {
return !opt.has_value() || *opt == byte;
});
if (match) {
return i;
}
}
return nullptr;
}

scan_result find_pattern(std::byte* begin, std::byte* end, signature_view signature) {
scan_result find_pattern<scan_mode::Auto>(std::byte* begin, std::byte* end, signature_view signature) {
const auto size = signature.size();
#if defined(LIBHAT_X86)
const auto& ext = get_system().extensions;
Expand Down
3 changes: 1 addition & 2 deletions src/arch/arm/Neon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
#ifdef LIBHAT_ARM

#include <libhat/Scanner.hpp>
#include <libhat/ScanMode.hpp>

namespace hat {
namespace hat::detail {

template<>
scan_result find_pattern<scan_mode::Neon>(std::byte* begin, std::byte* end, signature_view signature) {
Expand Down
3 changes: 1 addition & 2 deletions src/arch/x86/AVX2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
#ifdef LIBHAT_X86

#include <libhat/Scanner.hpp>
#include <libhat/ScanMode.hpp>

#include <immintrin.h>

namespace hat {
namespace hat::detail {

template<>
scan_result find_pattern<scan_mode::AVX2>(std::byte* begin, std::byte* end, signature_view signature) {
Expand Down
3 changes: 1 addition & 2 deletions src/arch/x86/AVX512.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
#ifdef LIBHAT_X86

#include <libhat/Scanner.hpp>
#include <libhat/ScanMode.hpp>

#include <immintrin.h>

namespace hat {
namespace hat::detail {

template<>
scan_result find_pattern<scan_mode::AVX512>(std::byte* begin, std::byte* end, signature_view signature) {
Expand Down

0 comments on commit e9409e6

Please sign in to comment.