mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-14 22:47:12 +00:00
util/formatted_output.h: hex-dump utility
Adds Genode::Hex_dump class to the formatted_output.h header. This class can be used to print a hexadecimal dump of a byte range. The data is printed in a format similar to that used by Linux's 'xxd'. In addition to the 'xxd' format, consecutive duplicate lines are replaced with a single "*\n" as done also by Linux's 'hexdump'. Ref #4966
This commit is contained in:
parent
9a94fbb1ec
commit
8bad3d08d7
@ -15,6 +15,7 @@
|
||||
#define _INCLUDE__OS__UTIL__FORMATTED_OUTPUT_H_
|
||||
|
||||
#include <base/output.h>
|
||||
#include <util/string.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
@ -23,6 +24,8 @@ namespace Genode {
|
||||
template <typename> struct Left_aligned;
|
||||
template <typename> struct Right_aligned;
|
||||
|
||||
class Hex_dump;
|
||||
|
||||
/**
|
||||
* Return the number of characters needed when rendering 'args' as text
|
||||
*/
|
||||
@ -119,4 +122,93 @@ struct Genode::Right_aligned
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Genode::Hex_dump
|
||||
{
|
||||
private:
|
||||
|
||||
static constexpr size_t _max_bytes_per_line { 16 };
|
||||
uint8_t const * const _base;
|
||||
size_t const _size;
|
||||
size_t const _num_lines { (_size + _max_bytes_per_line - 1) / _max_bytes_per_line };
|
||||
|
||||
static bool _printable_ascii(char c)
|
||||
{
|
||||
return c > 31 && c < 127;
|
||||
}
|
||||
|
||||
static void _print_line_as_hex_words(Output &out, uint8_t const *base, size_t size)
|
||||
{
|
||||
using Genode::print;
|
||||
static constexpr size_t max_bytes_per_word { 2 };
|
||||
for (size_t idx { 0 }; idx < _max_bytes_per_line; idx++) {
|
||||
|
||||
if (idx && idx % max_bytes_per_word == 0)
|
||||
print(out, " ");
|
||||
|
||||
if (idx < size)
|
||||
print(out, Hex(base[idx], Hex::OMIT_PREFIX, Hex::PAD));
|
||||
else
|
||||
print(out, " ");
|
||||
}
|
||||
}
|
||||
|
||||
static void _print_line_as_ascii(Output &out, uint8_t const *base, size_t size)
|
||||
{
|
||||
using Genode::print;
|
||||
for (size_t idx { 0 }; idx < size; idx++) {
|
||||
|
||||
char const *char_ptr { (char *)&base[idx] };
|
||||
if (_printable_ascii(*char_ptr))
|
||||
print(out, Cstring { char_ptr, 1 });
|
||||
else
|
||||
print(out, ".");
|
||||
}
|
||||
}
|
||||
|
||||
static void _print_line_offset(Output &out, size_t line_offset)
|
||||
{
|
||||
Genode::print(out, Hex((uint32_t)line_offset, Hex::OMIT_PREFIX, Hex::PAD));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Hex_dump(auto const &range)
|
||||
: _base { (uint8_t *)range.start }, _size { range.num_bytes } { }
|
||||
|
||||
void print(Output &out) const
|
||||
{
|
||||
using Genode::print;
|
||||
uint8_t const *prev_line_ptr { nullptr };
|
||||
bool prev_line_was_duplicate { false };
|
||||
for (size_t line_idx { 0 }; line_idx < _num_lines; line_idx++) {
|
||||
|
||||
size_t const line_offset { line_idx * _max_bytes_per_line };
|
||||
size_t const line_size { min((size_t)_max_bytes_per_line, _size - line_offset) };
|
||||
uint8_t const *line_ptr { &_base[line_offset] };
|
||||
bool const last_line { line_idx == _num_lines - 1 };
|
||||
|
||||
bool line_is_duplicate { false };
|
||||
if (prev_line_ptr)
|
||||
line_is_duplicate = !memcmp(prev_line_ptr, line_ptr, line_size);
|
||||
|
||||
if (!line_is_duplicate || last_line) {
|
||||
|
||||
_print_line_offset(out, line_offset);
|
||||
print(out, ": ");
|
||||
_print_line_as_hex_words(out, line_ptr, line_size);
|
||||
print(out, " ");
|
||||
_print_line_as_ascii(out, line_ptr, line_size);
|
||||
print(out, last_line ? "" : "\n");
|
||||
}
|
||||
if (line_is_duplicate && !prev_line_was_duplicate && !last_line)
|
||||
print(out, "*\n");
|
||||
|
||||
|
||||
prev_line_ptr = line_ptr;
|
||||
prev_line_was_duplicate = line_is_duplicate;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__OS__UTIL__FORMATTED_OUTPUT_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user