32 #ifndef HERMES_LOG_MEMORY_DUMP_H
33 #define HERMES_LOG_MEMORY_DUMP_H
111 color = console_color;
118 count = region_count;
133 std::size_t new_offset = 0;
138 if (increment_to_parent_size)
146 std::size_t new_offset = 0;
151 if (increment_to_parent_size)
159 type = DataTypes::typeFrom<T>();
168 count = element_count;
177 count = element_count;
214 static std::string
dumpInfo(
const T *data, std::size_t size) {
215 auto alignment =
alignof(T);
216 auto ptr =
reinterpret_cast<const u8 *
>(data);
217 ptrdiff_t down_shift =
reinterpret_cast<uintptr_t
>(ptr) & (64 - 1);
218 uintptr_t aligned_base_address =
reinterpret_cast<uintptr_t
>(ptr) - down_shift;
219 auto size_in_bytes =
sizeof(T) * size + down_shift;
220 Str s =
"Memory Block Information\n";
222 s.
appendLine(
" Block Size:\t",
sizeof(T) * size,
" bytes");
224 s.
appendLine(
" Type Alignment:\t", alignment);
227 s.
appendLine(
" Total Block Size:\t", size_in_bytes,
" bytes");
239 static std::string
dump(
const T *data, std::size_t size,
u32 bytes_per_row = 8,
244 auto include_header = !
HERMES_MASK_BIT(options, memory_dumper_options::hide_header);
245 auto align_data =
HERMES_MASK_BIT(options, memory_dumper_options::cache_align);
248 auto save_string =
HERMES_MASK_BIT(options, memory_dumper_options::save_to_string);
250 auto show_type_values =
HERMES_MASK_BIT(options, memory_dumper_options::type_values);
256 u32 address_digit_count = 8;
258 u8 data_digit_count = 2;
260 data_digit_count = 3;
262 data_digit_count = 8;
264 u8 column_size = std::max(header_digit_count, data_digit_count);
265 u8 address_column_size = address_digit_count + 2 + 2;
266 if (include_header) {
267 Str s = std::string(address_column_size,
' ');
268 for (
u32 i = 0; i < bytes_per_row; ++i) {
272 s.
append(std::setw(column_size), !bs.empty() ? bs :
"0",
" ");
279 auto alignment = (align_data) ? 64 : 1;
280 auto ptr =
reinterpret_cast<const u8 *
>(data);
281 ptrdiff_t shift =
reinterpret_cast<uintptr_t
>(ptr) & (alignment - 1);
282 uintptr_t aligned_base_address =
reinterpret_cast<uintptr_t
>(ptr) - shift;
283 ptrdiff_t byte_offset = 0;
284 ptrdiff_t size_in_bytes =
sizeof(T) * size + shift;
286 while (byte_offset < size_in_bytes) {
290 s.
append(
Str::addressOf(
reinterpret_cast<uintptr_t
>((
void *) (aligned_base_address + byte_offset))).c_str(),
302 std::string ascii_data;
304 for (ptrdiff_t i = 0; i < bytes_per_row; i++, byte_offset++) {
309 output_string.
append(
" ");
311 if (aligned_base_address + byte_offset <
reinterpret_cast<uintptr_t
>(ptr) || byte_offset >= size_in_bytes) {
313 std::cout << std::string(column_size,
' ') +
" ";
315 output_string += std::string(column_size,
' ') +
" ";
319 u8 byte = *(
reinterpret_cast<u8 *
>(aligned_base_address + byte_offset));
325 s.
append(std::setfill(
'0'), std::setw(column_size),
static_cast<u32>(
byte),
' ');
329 s.
append(std::string(column_size,
' '),
" ");
333 s.
append(std::string(column_size,
' '),
" ");
337 std::string current_byte_color = byteColor(byte_offset - shift, region);
342 std::cout << s.
str();
345 ascii_data += current_byte_color;
346 if (std::isalnum(
byte))
355 if (show_type_values) {
359 typeValue(byte_offset - shift,
reinterpret_cast<u8 *
>(aligned_base_address + byte_offset), region);
369 std::cout <<
"\t|" << ascii_data <<
"|";
371 output_string.
append(
"\t|", ascii_data,
"|");
373 if (show_type_values) {
381 output_string +=
'\n';
384 return output_string.
str();
388 static std::string byteColor(std::size_t byte_index,
const RegionLayout ®ion) {
389 std::function<std::string(
const std::vector<RegionLayout> &, std::size_t,
const std::string &)> f;
390 f = [&](
const std::vector<RegionLayout> &subregions, std::size_t byte_offset,
391 const std::string &parent_color) -> std::string {
392 for (
const auto &sub_region : subregions) {
393 auto region_start = sub_region.offset;
394 auto region_end = region_start + sub_region.field_size_in_bytes * sub_region.count;
395 if (byte_offset >= region_start && byte_offset < region_end) {
396 if (sub_region.sub_regions.empty()) {
399 if (((byte_offset - region_start) / sub_region.field_size_in_bytes) % 2)
401 return sub_region.color;
403 return f(sub_region.sub_regions,
404 (byte_offset - region_start) % sub_region.field_size_in_bytes,
413 static std::string typeValue(std::size_t byte_index,
u8 *data,
const RegionLayout ®ion) {
414 std::function<std::string(
const std::vector<RegionLayout> &, std::size_t,
const std::string &)> f;
415 f = [&](
const std::vector<RegionLayout> &subregions, std::size_t byte_offset,
416 const std::string &parent_color) -> std::string {
418 for (
const auto &sub_region : subregions) {
419 auto region_start = sub_region.offset;
420 auto region_end = region_start + sub_region.field_size_in_bytes * sub_region.count;
421 if (byte_offset >= region_start && byte_offset < region_end) {
422 if (sub_region.sub_regions.empty() && sub_region.type != DataType::CUSTOM) {
424 std::stringstream ss;
425 #define RETURN_TYPE(T) if(sub_region.type == DataTypes::typeFrom<T>()) { \
426 ss << std::setw(10) << std::right << std::setprecision(3) << *reinterpret_cast<T*>(data); \
443 return f(sub_region.sub_regions,
444 (byte_offset - region_start) % sub_region.field_size_in_bytes,
460 os << layout.
color <<
"MemoryRegionLayout [offset = " << layout.
offset;
462 os <<
" count = " << layout.
count;
464 os <<
"\tsub regions [" << layout.
sub_regions.size() <<
"]\n";
Support of bitwise operations for compatible enum classes.
#define HERMES_MASK_BIT(MASK, BIT)
Tests if enum class value is enabled.
Definition: bitmask_operators.h:84
#define HERMES_ENABLE_BITMASK_OPERATORS(x)
Adds bitwise operation support to a given enum class.
Definition: bitmask_operators.h:58
static std::string combine(const std::string &a, const std::string &b)
Combine two color codes.
Definition: console_colors.h:112
static char bold[5]
"\e[1m"
Definition: console_colors.h:46
static char reset[5]
"\e[0m"
Definition: console_colors.h:53
static char dim[5]
"\e[2m"
Definition: console_colors.h:47
static char reset_dim[6]
"\e[22m"
Definition: console_colors.h:55
static char default_color[6]
"\e[39m"
Definition: console_colors.h:61
static std::string typeName(DataType type)
Gets DataType string name.
Definition: defs.h:183
static u32 typeSize(DataType type)
Computes number of bytes from DataType.
Definition: defs.h:163
Auxiliary logging class for printing blocks of memory.
Definition: memory_dump.h:71
static std::string dump(const T *data, std::size_t size, u32 bytes_per_row=8, const RegionLayout ®ion=RegionLayout(), memory_dumper_options options=memory_dumper_options::none)
Dumps memory region.
Definition: memory_dump.h:239
static std::string dumpInfo(const T *data, std::size_t size)
Dumps memory info about a given memory region.
Definition: memory_dump.h:214
String class and set of string functions.
Definition: str.h:53
static std::string binaryToHex(T input_n, bool uppercase=true, bool strip_leading_zeros=false)
Get ascii representation of raw bit data of input_n
Definition: str.h:267
void append(const Args &... args)
Append arguments to this Str.
Definition: str.h:404
static std::string addressOf(uintptr_t ptr, u32 digit_count=8)
Generates hexadecimal representation of memory address.
Definition: str.h:291
const std::string & str() const
Get std::string object.
Definition: str.h:381
void appendLine(const Args &... args)
Append arguments to this Str followed by a breakline.
Definition: str.h:414
static std::string byteToBinary(byte b)
Binary representation of byte.
Definition: str.h:303
Set of 256-terminal supported color codes.
Debug, logging and assertion macros.
DataType
Enum class for integral types.
Definition: defs.h:101
int8_t i8
8 bit size integer type
Definition: defs.h:81
uint64_t u64
64 bit size unsigned integer type
Definition: defs.h:89
#define HERMES_UNUSED_VARIABLE(x)
Specifies that variable is not used in this scope.
Definition: debug.h:62
uint8_t byte
unsigned byte
Definition: defs.h:96
uint16_t u16
16 bit size unsigned integer type
Definition: defs.h:87
uint32_t u32
32 bit size unsigned integer type
Definition: defs.h:88
int64_t i64
64 bit size integer type
Definition: defs.h:84
int16_t i16
16 bit size integer type
Definition: defs.h:82
uint8_t u8
8 bit size unsigned integer type
Definition: defs.h:86
double f64
64 bit size floating point type
Definition: defs.h:79
float f32
32 bit size floating point type
Definition: defs.h:78
int32_t i32
32 bit size integer type
Definition: defs.h:83
memory_dumper_options
MemoryDumper output options.
Definition: memory_dump.h:49
@ hexadecimal
output memory contents in hexadecimal
@ hexii
output memory contents in hexii
@ cache_align
aligns starting address to cache size
@ write_to_console
directly dump into stdout
@ binary
output memory contents in binary
@ decimal
output memory contents in decimal
@ hide_zeros
do not output bytes with 0 as value
@ save_to_string
redirect output to string
@ type_values
cast values and output their values properly
@ hide_header
hide memory column names
@ show_ascii
show ascii characters for each memory byte
@ colored_output
use terminal colors
Memory region description.
Definition: memory_dump.h:97
std::size_t count
Region count.
Definition: memory_dump.h:199
void pushSubRegion(const RegionLayout &sub_region, bool increment_to_parent_size=false)
Appends a layout representing a sub-region of this layout.
Definition: memory_dump.h:145
void clear()
Removes all description.
Definition: memory_dump.h:193
RegionLayout & withOffset(std::size_t offset_in_bytes)
Modifies layout offset.
Definition: memory_dump.h:103
std::size_t sizeInBytes() const
Gets layout size in bytes.
Definition: memory_dump.h:183
void resizeSubRegions(size_t sub_regions_count)
Resizes number of sub-regions of this layout.
Definition: memory_dump.h:186
RegionLayout & withTypeFrom()
Modifies layout base data type based on a given type.
Definition: memory_dump.h:158
DataType type
Base data type.
Definition: memory_dump.h:202
RegionLayout & withColor(const std::string &console_color)
Modifies layout color.
Definition: memory_dump.h:110
std::string color
Region color.
Definition: memory_dump.h:200
RegionLayout & withSizeOf(std::size_t element_count=1)
Modifies layout size based on given type and count.
Definition: memory_dump.h:167
RegionLayout & withType(DataType t)
Modifies layout base data type.
Definition: memory_dump.h:124
RegionLayout & withSize(std::size_t size_in_bytes, std::size_t element_count=1)
Modifies layout size based on given quantities.
Definition: memory_dump.h:176
RegionLayout & withCount(std::size_t region_count)
Modifies layout count.
Definition: memory_dump.h:117
std::vector< RegionLayout > sub_regions
Sub-region descriptions.
Definition: memory_dump.h:201
RegionLayout()=default
Default constructor.
RegionLayout & withSubRegion(const RegionLayout &sub_region, bool increment_to_parent_size=false)
Appends a layout representing a sub-region of this layout.
Definition: memory_dump.h:132
std::size_t field_size_in_bytes
Region size.
Definition: memory_dump.h:198
std::size_t offset
Layout offset in bytes.
Definition: memory_dump.h:197
static HERMES_DEVICE_CALLABLE u8 countHexDigits(T n)
Counts hexadecimal digits.
Definition: numeric.h:161