|
| 1 | +#include "util/hex-dumper.h" |
| 2 | + |
| 3 | +#include "io/file-utils.h" |
| 4 | + |
| 5 | +namespace util { |
| 6 | +namespace { |
| 7 | + |
| 8 | +inline char to_hex(int value) { |
| 9 | + return value < 10 ? '0' + value : 'a' + value - 10; |
| 10 | +} |
| 11 | + |
| 12 | +inline char to_char(int value) { |
| 13 | + return value >= 32 && value <= 127 ? value : '.'; |
| 14 | +} |
| 15 | + |
| 16 | +void put_uint8_hex(uint8_t value, char output[2]) { |
| 17 | + output[0] = to_hex(value >> 4); |
| 18 | + output[1] = to_hex(value & 0xf); |
| 19 | +} |
| 20 | + |
| 21 | +void put_uint32_hex(uint32_t value, char output[8]) { |
| 22 | + for (int i = 0; i < 8; ++i) { |
| 23 | + output[i] = to_hex(value >> 28); |
| 24 | + value <<= 4; |
| 25 | + } |
| 26 | +} |
| 27 | + |
| 28 | +} // namespace |
| 29 | + |
| 30 | +HexDumper::HexDumper(int width) |
| 31 | + : width_(width), |
| 32 | + buffer_(char_start() + width_ + 1, ' ') {} |
| 33 | + |
| 34 | +std::error_code HexDumper::dump( |
| 35 | + uint32_t offset, ConstBufferSpan input, io::File &output) { |
| 36 | + while (input.size() >= width_) { |
| 37 | + std::error_code ec = dump_line(offset, input, output); |
| 38 | + if (ec) { |
| 39 | + return ec; |
| 40 | + } |
| 41 | + offset += width_; |
| 42 | + input.remove_prefix(width_); |
| 43 | + } |
| 44 | + if (!input.empty()) { |
| 45 | + std::error_code ec = dump_line(offset, input, output); |
| 46 | + if (ec) { |
| 47 | + return ec; |
| 48 | + } |
| 49 | + } |
| 50 | + return {}; |
| 51 | +} |
| 52 | + |
| 53 | +std::error_code HexDumper::dump_line( |
| 54 | + uint32_t offset, ConstBufferSpan input, io::File &output) { |
| 55 | + const size_t size = std::min(input.size(), width_); |
| 56 | + put_uint32_hex(offset, &buffer_[0]); |
| 57 | + buffer_[8] = ':'; |
| 58 | + size_t i; |
| 59 | + for (i = 0; i < size; ++i) { |
| 60 | + put_uint8_hex(input[i], &buffer_[i * 5 / 2 + 10]); |
| 61 | + buffer_[char_start() + i] = to_char(input[i]); |
| 62 | + } |
| 63 | + for (; i < width_; ++i) { |
| 64 | + buffer_[i * 5 / 2 + 10] = ' '; |
| 65 | + buffer_[i * 5 / 2 + 11] = ' '; |
| 66 | + } |
| 67 | + buffer_[char_start() + size] = '\n'; |
| 68 | + return io::write(output, {buffer_.data(), char_start() + size + 1}); |
| 69 | +} |
| 70 | + |
| 71 | +} // namespace util |
0 commit comments