1414
1515namespace hat {
1616
17- template <typename T> requires (std::is_pointer_v<T> && sizeof (std:: remove_pointer_t <T> ) == 1)
17+ template <typename T> requires (sizeof (T ) == 1)
1818 class scan_result_base {
19- using rel_t = int32_t ;
2019 public:
21- using underlying_type = T;
20+ using underlying_type = T* ;
2221
23- constexpr scan_result_base () : result (nullptr ) {}
24- constexpr scan_result_base (std::nullptr_t ) : result (nullptr ) {} // NOLINT(google-explicit-constructor)
25- constexpr scan_result_base (T result) : result (result) {} // NOLINT(google-explicit-constructor)
22+ constexpr scan_result_base () noexcept : result (nullptr ) {}
23+ explicit ( false ) constexpr scan_result_base (std::nullptr_t ) noexcept : result (nullptr ) {}
24+ explicit ( false ) constexpr scan_result_base (const underlying_type result) noexcept : result (result) {}
2625
2726 // / Reads an integer of the specified type located at an offset from the signature result
2827 template <std::integral Int>
29- [[nodiscard]] constexpr Int read (size_t offset) const {
28+ [[nodiscard]] constexpr Int read (const size_t offset) const noexcept {
3029 if LIBHAT_IF_CONSTEVAL {
31- constexpr size_t sz = sizeof (Int);
30+ constexpr size_t N = sizeof (Int);
3231 return std::bit_cast<Int>([=, this ]<size_t ... Index>(std::index_sequence<Index...>) {
33- return std::array<std::byte, sz >{(this ->result + offset)[Index]...};
34- }(std::make_index_sequence<sz >{}));
32+ return std::array<T, N >{(this ->result + offset)[Index]...};
33+ }(std::make_index_sequence<N >{}));
3534 } else {
3635 Int value;
3736 std::memcpy (&value, this ->result + offset, sizeof (Int));
@@ -41,7 +40,7 @@ namespace hat {
4140
4241 // / Reads an integer of the specified type which represents an index into an array with the given element type
4342 template <std::integral Int, typename ArrayType>
44- [[nodiscard]] constexpr size_t index (size_t offset) const {
43+ [[nodiscard]] constexpr size_t index (const size_t offset) const noexcept {
4544 return static_cast <size_t >(read<Int>(offset)) / sizeof (ArrayType);
4645 }
4746
@@ -68,29 +67,31 @@ namespace hat {
6867 // / The "0x0" operand comes after the relative address. The absolute address referred to by the RIP relative
6968 // / address in this case is 0x12353BE + 0x7 = 0x12353C5. Simply using rel(2) would yield an incorrect result of
7069 // / 0x12353C4. In this case, rel(2, 1) would yield the expected 0x12353C5.
71- [[nodiscard]] constexpr T rel (size_t offset, size_t remaining = 0 ) const {
72- return this ->result + this ->read <rel_t >(offset) + offset + sizeof (rel_t ) + remaining;
70+ [[nodiscard]] constexpr underlying_type rel (size_t offset, size_t remaining = 0 ) const noexcept {
71+ using rel32_t = int32_t ;
72+ return this ->result + this ->read <rel32_t >(offset) + offset + sizeof (rel32_t ) + remaining;
7373 }
7474
75- [[nodiscard]] constexpr bool has_result () const {
75+ [[nodiscard]] constexpr bool has_result () const noexcept {
7676 return this ->result != nullptr ;
7777 }
7878
79- [[nodiscard]] constexpr T operator *() const {
79+ [[nodiscard]] constexpr underlying_type operator *() const noexcept {
8080 return this ->result ;
8181 }
8282
83- [[nodiscard]] constexpr T get () const {
83+ [[nodiscard]] constexpr underlying_type get () const noexcept {
8484 return this ->result ;
8585 }
8686
8787 [[nodiscard]] constexpr auto operator <=>(const scan_result_base&) const noexcept = default ;
88+
8889 private:
89- T result;
90+ underlying_type result;
9091 };
9192
92- using scan_result = scan_result_base<std::byte* >;
93- using const_scan_result = scan_result_base<const std::byte* >;
93+ using scan_result = scan_result_base<std::byte>;
94+ using const_scan_result = scan_result_base<const std::byte>;
9495
9596 enum class scan_alignment : uint8_t {
9697 X1 = 1 ,
0 commit comments