13 return (
'0' <= a_ch && a_ch <=
'9') ||
14 (
'A' <= a_ch && a_ch <=
'F') ||
15 (
'a' <= a_ch && a_ch <=
'f');
18 [[nodiscard]]
constexpr bool space(
char a_ch)
noexcept
23 [[nodiscard]]
constexpr bool wildcard(
char a_ch)
noexcept
35 constexpr auto lut = []()
noexcept {
36 std::array<std::uint8_t, std::numeric_limits<unsigned char>::max() + 1> a = {};
38 const auto iterate = [&](std::uint8_t a_iFirst,
unsigned char a_cFirst,
unsigned char a_cLast)
noexcept {
39 for (; a_cFirst <= a_cLast; ++a_cFirst, ++a_iFirst) {
40 a[a_cFirst] = a_iFirst;
45 iterate(0xA,
'A',
'F');
46 iterate(0xa,
'a',
'f');
51 return static_cast<std::byte
>(
52 lut[
static_cast<unsigned char>(a_hi)] * 0x10u +
53 lut[
static_cast<unsigned char>(a_lo)]);
57 template <
char HI,
char LO>
61 [[nodiscard]]
static constexpr bool match(std::byte a_byte)
noexcept
64 return a_byte == expected;
83 [[nodiscard]]
static constexpr bool match(std::byte)
noexcept
97 template <
char C1,
char C2>
99 requires(characters::hexadecimal(C1) && characters::hexadecimal(C2));
101 template <
char C1,
char C2>
103 requires(characters::wildcard(C1) && characters::wildcard(C2));
106 template <class... Rules>
110 static_assert(
sizeof...(Rules) >= 1,
"must provide at least 1 rule for the pattern matcher");
112 [[nodiscard]]
constexpr bool match(std::span<
const std::byte,
sizeof...(Rules)> a_bytes)
const noexcept
115 return (Rules::match(a_bytes[i++]) && ...);
118 [[nodiscard]]
bool match(std::uintptr_t a_address)
const noexcept
120 return this->match(*
reinterpret_cast<const std::byte(*)[sizeof...(Rules)]
>(a_address));
123 void match_or_fail(std::uintptr_t a_address, std::source_location a_loc = std::source_location::current()) const noexcept
125 if (!this->match(a_address)) {
129 "A pattern has failed to match.\n"
130 "This means the plugin is incompatible with the current version of the game ({}.{}.{}). "
131 "Head to the mod page of this plugin to see if an update is available."sv,
142 template <stl::nttp::string S,
class... Rules>
145 if constexpr (S.length() == 0) {
147 }
else if constexpr (S.length() == 1) {
148 constexpr char c = S[0];
150 consteval_error(
"the given pattern has an unpaired rule (rules are required to be written in pairs of 2)");
152 consteval_error(
"the given pattern has trailing characters at the end (which is not allowed)");
155 using rule_t =
decltype(rules::rule_for<S[0], S[1]>());
156 if constexpr (std::same_as<rule_t, void>) {
159 if constexpr (S.length() <= 3) {
164 consteval_error(
"a space character is required to split byte patterns");
170 template <
class... Bytes>
172 -> std::array<std::byte,
sizeof...(Bytes)>
174 static_assert((std::integral<Bytes> && ...),
"all bytes must be an integral type");
175 return {
static_cast<std::byte
>(a_bytes)... };
179 template <stl::nttp::
string S>
182 return detail::do_make_pattern<S>();
187 static_assert(
make_pattern<
"B8 D0 ?? ?? D4 6E">().match(
Version version() const noexcept
Definition Module.h:62
static Module & get()
Definition Module.h:54
constexpr bool match(std::span< const std::byte, sizeof...(Rules)> a_bytes) const noexcept
Definition Pattern.h:112
void match_or_fail(std::uintptr_t a_address, std::source_location a_loc=std::source_location::current()) const noexcept
Definition Pattern.h:123
bool match(std::uintptr_t a_address) const noexcept
Definition Pattern.h:118
static constexpr bool match(std::byte a_byte) noexcept
Definition Pattern.h:61
static constexpr bool match(std::byte) noexcept
Definition Pattern.h:83
constexpr bool space(char a_ch) noexcept
Definition Pattern.h:18
constexpr bool hexadecimal(char a_ch) noexcept
Definition Pattern.h:11
constexpr bool wildcard(char a_ch) noexcept
Definition Pattern.h:23
consteval std::byte hexacharacters_to_hexadecimal(char a_hi, char a_lo) noexcept
Definition Pattern.h:33
consteval auto make_byte_array(Bytes... a_bytes) noexcept -> std::array< std::byte, sizeof...(Bytes)>
Definition Pattern.h:171
void consteval_error(const char *a_error)
constexpr auto do_make_pattern() noexcept
Definition Pattern.h:143
constexpr auto make_pattern() noexcept
Definition Pattern.h:180
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition PCH.h:397