Skip to content

Commit 3b70804

Browse files
committed
util:dump-hex
1 parent d9245cd commit 3b70804

File tree

4 files changed

+150
-0
lines changed

4 files changed

+150
-0
lines changed

util/BUILD

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
package(default_visibility = ["//visibility:public"])
22

3+
cc_library(
4+
name = "dump-hex",
5+
srcs = ["dump-hex.cc"],
6+
hdrs = ["dump-hex.h"],
7+
deps = [
8+
"//base:types",
9+
"//io:file",
10+
"//io:file-utils",
11+
"@com_google_absl//absl/container:fixed_array",
12+
],
13+
)
14+
15+
cc_test(
16+
name = "dump-hex_test",
17+
srcs = ["dump-hex_test.cc"],
18+
deps = [
19+
":dump-hex",
20+
"//base:types",
21+
"//io:memory-file",
22+
"@com_google_googletest//:gtest_main",
23+
],
24+
)
25+
326
cc_library(
427
name = "fibonacci-sequence",
528
hdrs = ["fibonacci-sequence.h"],

util/dump-hex.cc

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

util/dump-hex.h

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef _UTIL_DUMP_HEX_H
2+
#define _UTIL_DUMP_HEX_H
3+
4+
#include <cstdint>
5+
#include <system_error>
6+
7+
#include "base/types.h"
8+
#include "io/file.h"
9+
10+
namespace util {
11+
12+
struct DumpHexOptions {
13+
int width = 16;
14+
uint32_t offset = 0;
15+
};
16+
17+
std::error_code dump_hex(
18+
ConstBufferSpan input,
19+
io::File &output,
20+
const DumpHexOptions &options);
21+
22+
} // namespace util
23+
24+
#endif // _UTIL_DUMP_HEX_H

util/dump-hex_test.cc

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include "util/dump-hex.h"
2+
3+
#include <string_view>
4+
#include <system_error>
5+
#include <gtest/gtest.h>
6+
7+
#include "base/types.h"
8+
#include "io/memory-file.h"
9+
10+
namespace util {
11+
namespace {
12+
13+
TEST(DumpHexTest, basic) {
14+
io::MemoryFile file;
15+
DumpHexOptions options;
16+
options.width = 7;
17+
options.offset = 12;
18+
EXPECT_EQ(dump_hex("hello world\n", file, options), std::error_code());
19+
EXPECT_EQ(std::string_view(ConstBufferSpan(file.content())),
20+
"0000000c: 6865 6c6c 6f20 77 hello w\n"
21+
"00000013: 6f72 6c64 0a orld.\n");
22+
}
23+
24+
} // namespace
25+
} // namespace util

0 commit comments

Comments
 (0)