Skip to content

Commit

Permalink
util:hex-dumper
Browse files Browse the repository at this point in the history
  • Loading branch information
iceboy233 committed Jun 30, 2024
1 parent d9245cd commit 177d65d
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 0 deletions.
23 changes: 23 additions & 0 deletions util/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,29 @@ cc_test(
],
)

cc_library(
name = "hex-dumper",
srcs = ["hex-dumper.cc"],
hdrs = ["hex-dumper.h"],
deps = [
"//base:types",
"//io:file",
"//io:file-utils",
"@com_google_absl//absl/container:fixed_array",
],
)

cc_test(
name = "hex-dumper_test",
srcs = ["hex-dumper_test.cc"],
deps = [
":hex-dumper",
"//base:types",
"//io:memory-file",
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "pod",
hdrs = ["pod.h"],
Expand Down
73 changes: 73 additions & 0 deletions util/hex-dumper.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "util/hex-dumper.h"

#include <algorithm>

#include "io/file-utils.h"

namespace util {
namespace {

inline char to_hex(int value) {
return value < 10 ? '0' + value : 'a' + value - 10;
}

inline char to_char(int value) {
return value >= 32 && value <= 127 ? value : '.';
}

void put_uint8_hex(uint8_t value, char output[2]) {
output[0] = to_hex(value >> 4);
output[1] = to_hex(value & 0xf);
}

void put_uint32_hex(uint32_t value, char output[8]) {
for (int i = 0; i < 8; ++i) {
output[i] = to_hex(value >> 28);
value <<= 4;
}
}

} // namespace

HexDumper::HexDumper(int width)
: width_(width),
buffer_(char_start() + width_ + 1, ' ') {}

std::error_code HexDumper::dump(
uint32_t offset, ConstBufferSpan input, io::File &output) {
while (input.size() >= width_) {
std::error_code ec = dump_line(offset, input, output);
if (ec) {
return ec;
}
offset += width_;
input.remove_prefix(width_);
}
if (!input.empty()) {
std::error_code ec = dump_line(offset, input, output);
if (ec) {
return ec;
}
}
return {};
}

std::error_code HexDumper::dump_line(
uint32_t offset, ConstBufferSpan input, io::File &output) {
put_uint32_hex(offset, &buffer_[0]);
buffer_[8] = ':';
const size_t size = std::min(input.size(), width_);
size_t i;
for (i = 0; i < size; ++i) {
put_uint8_hex(input[i], &buffer_[i * 5 / 2 + 10]);
buffer_[char_start() + i] = to_char(input[i]);
}
for (; i < width_; ++i) {
buffer_[i * 5 / 2 + 10] = ' ';
buffer_[i * 5 / 2 + 11] = ' ';
}
buffer_[char_start() + size] = '\n';
return io::write(output, {buffer_.data(), char_start() + size + 1});
}

} // namespace util
32 changes: 32 additions & 0 deletions util/hex-dumper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef _UTIL_HEX_DUMPER_H
#define _UTIL_HEX_DUMPER_H

#include <cstddef>
#include <cstdint>
#include <system_error>

#include "absl/container/fixed_array.h"
#include "base/types.h"
#include "io/file.h"

namespace util {

class HexDumper {
public:
explicit HexDumper(int width = 16);

std::error_code dump(
uint32_t offset, ConstBufferSpan input, io::File &output);
std::error_code dump_line(
uint32_t offset, ConstBufferSpan input, io::File &output);

private:
size_t char_start() const { return (width_ * 5 + 23) / 2; }

const size_t width_;
absl::FixedArray<char, 80> buffer_;
};

} // namespace util

#endif // _UTIL_HEX_DUMPER_H
23 changes: 23 additions & 0 deletions util/hex-dumper_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "util/hex-dumper.h"

#include <string_view>
#include <system_error>
#include <gtest/gtest.h>

#include "base/types.h"
#include "io/memory-file.h"

namespace util {
namespace {

TEST(DumpHexTest, basic) {
HexDumper dumper(7);
io::MemoryFile file;
EXPECT_EQ(dumper.dump(12, "hello world\n", file), std::error_code());
EXPECT_EQ(std::string_view(ConstBufferSpan(file.content())),
"0000000c: 6865 6c6c 6f20 77 hello w\n"
"00000013: 6f72 6c64 0a orld.\n");
}

} // namespace
} // namespace util

0 comments on commit 177d65d

Please sign in to comment.