15#include "../microfmt.hpp"
16#include "../reloco.hpp"
29 uintptr_t base_address{0};
30 uint8_t bytes_per_row{16};
45RELOCO_BEGIN_UNSAFE_CODE
46template <
typename T1,
typename T2>
48 span<const std::byte> new_span,
49 uintptr_t base_addr = 0) noexcept {
51 span<const std::byte>(
reinterpret_cast<const std::byte *
>(old_span.data()), old_span.size_bytes()),
52 span<const std::byte>(
reinterpret_cast<const std::byte *
>(new_span.data()), new_span.size_bytes()), base_addr,
60RELOCO_BEGIN_UNSAFE_CODE
61template <
typename T1,
typename T2>
63 uintptr_t base_addr = 0) noexcept {
65 span<const std::byte>(
reinterpret_cast<const std::byte *
>(old_span.data()), old_span.size_bytes()),
66 span<const std::byte>(
reinterpret_cast<const std::byte *
>(new_span.data()), new_span.size_bytes()), base_addr,
71#if RELOCO_HAS_STD_SPAN
77RELOCO_BEGIN_UNSAFE_CODE
78template <
typename T1,
typename T2, std::
size_t Extent1, std::
size_t Extent2>
79[[nodiscard]]
constexpr memory_diff_view
mem_diff(std::span<const T1, Extent1> old_span,
80 std::span<const std::byte, Extent2> new_span,
81 uintptr_t base_addr = 0) noexcept {
82 return memory_diff_view{
83 span<const std::byte>(
reinterpret_cast<const std::byte *
>(old_span.data()), old_span.size_bytes()),
84 span<const std::byte>(
reinterpret_cast<const std::byte *
>(new_span.data()), new_span.size_bytes()), base_addr,
91RELOCO_BEGIN_UNSAFE_CODE
92template <
typename T1,
typename T2, std::
size_t Extent1, std::
size_t Extent2>
93[[nodiscard]]
constexpr memory_diff_view
mem_diff(std::span<const T1, Extent1> old_span,
94 std::span<const T2, Extent2> new_span,
95 uintptr_t base_addr = 0) noexcept {
96 return memory_diff_view{
97 span<const std::byte>(
reinterpret_cast<const std::byte *
>(old_span.data()), old_span.size_bytes()),
98 span<const std::byte>(
reinterpret_cast<const std::byte *
>(new_span.data()), new_span.size_bytes()), base_addr,
118 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
119 const size_t total_size = std::min(diff.old_data.size(), diff.new_data.size());
120 const size_t row_size = (diff.bytes_per_row > 0) ?
size_t{diff.bytes_per_row} :
size_t{16};
122 size_t identical_rows_streak = 0;
125 while (offset < total_size) {
126 const size_t current_chunk_size = std::min(row_size, total_size - offset);
129 bool rows_match =
true;
130 for (
size_t i = 0; i < current_chunk_size; ++i) {
131 if (diff.old_data[offset + i] != diff.new_data[offset + i]) {
138 identical_rows_streak++;
141 if (identical_rows_streak > 0) {
142 out.write(microfmt::string_view(
" [... "));
143 detail::format_unsigned<detail::radix::decimal>(out, identical_rows_streak,
false, 0);
144 out.write(microfmt::string_view(
" identical rows hidden ...]\n"));
145 identical_rows_streak = 0;
149 out.write(microfmt::string_view(
" 0x"));
150 detail::format_unsigned<detail::radix::hex>(out, diff.base_address + offset,
false, 8);
151 out.write(microfmt::string_view(
": "));
154 format_row_bytes(out, diff.old_data.subspan(offset, current_chunk_size));
155 out.write(microfmt::string_view(
" -> "));
158 format_row_bytes(out, diff.new_data.subspan(offset, current_chunk_size));
159 out.write(microfmt::string_view(
"\n"));
166 if (identical_rows_streak > 0) {
167 out.write(microfmt::string_view(
" [... "));
168 detail::format_unsigned<detail::radix::decimal>(out, identical_rows_streak,
false, 0);
169 out.write(microfmt::string_view(
" identical rows hidden ...]\n"));
171 RELOCO_END_UNSAFE_BUFFER_USAGE;
175 static void format_row_bytes(
const sink &out, span<const std::byte> chunk)
noexcept {
176 for (
size_t i = 0; i < chunk.size(); ++i) {
177 detail::format_unsigned<detail::radix::hex>(out,
static_cast<uint64_t
>(chunk[i]),
true, 2);
178 out.write(microfmt::string_view(
" ", 1));
Definition microfmt.hpp:881
#define MICROFMT_API_CLASS
Definition compat.hpp:181
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_END_UNSAFE_CODE
Definition remote_object.hpp:132
RELOCO_BEGIN_UNSAFE_CODE constexpr memory_diff_view mem_diff(span< const T1 > old_span, span< const std::byte > new_span, uintptr_t base_addr=0) noexcept
Creates a memory diff view over two microfmt::span containers.
Definition memory_diff.hpp:47
Non-owning view representing a byte-level comparison between two memory regions.
Definition memory_diff.hpp:26
span< const std::byte > old_data
Definition memory_diff.hpp:27
span< const std::byte > new_data
Definition memory_diff.hpp:28