OXYGENHUB
◆ main openmsx / src / utils / HexDump.cc
2.0 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "HexDump.hh"
2
3
#include "narrow.hh"
4
5
#include "strCat.hh"
6
#include "xrange.hh"
7
#include <algorithm>
8
#include <cassert>
9
10
namespace HexDump {
11
12
using openmsx::MemBuffer;
13
14
[[nodiscard]] static constexpr char encode2(uint8_t x)
15
{
16
	return (x < 10) ? char(x + '0') : char(x - 10 + 'A');
17
}
18
[[nodiscard]] static auto encode(uint8_t x)
19
{
20
	return tmpStrCat(encode2(x >> 4), encode2(x & 15));
21
}
22
std::string encode(std::span<const uint8_t> input, bool newlines)
23
{
24
	std::string ret;
25
	size_t in = 0;
26
	auto len = input.size();
27
	while (len) {
28
		if (newlines && !ret.empty()) ret += '\n';
29
		auto t = int(std::min<size_t>(16, len));
30
		for (auto i : xrange(t)) {
31
			ret += encode(input[in++]);
32
			if (i != (t - 1)) ret += ' ';
33
		}
34
		len -= t;
35
	}
36
	return ret;
37
}
38
39
[[nodiscard]] static constexpr int decode(char x)
40
{
41
	if (('0' <= x) && (x <= '9')) {
42
		return x - '0';
43
	} else if (('A' <= x) && (x <= 'F')) {
44
		return x - 'A' + 10;
45
	} else if (('a' <= x) && (x <= 'f')) {
46
		return x - 'a' + 10;
47
	} else {
48
		return -1;
49
	}
50
}
51
MemBuffer<uint8_t> decode(std::string_view input)
52
{
53
	auto inSize = input.size();
54
	auto outSize = inSize / 2; // overestimation
55
	MemBuffer<uint8_t> ret(outSize); // too big
56
57
	size_t out = 0;
58
	bool flip = true;
59
	uint8_t tmp = 0;
60
	for (char c : input) {
61
		int d = decode(c);
62
		if (d == -1) continue;
63
		assert(d >= 0);
64
		assert(d <= 15);
65
		if (flip) {
66
			tmp = narrow<uint8_t>(d);
67
		} else {
68
			ret[out++] = narrow<uint8_t>((tmp << 4) | d);
69
		}
70
		flip = !flip;
71
	}
72
73
	assert(outSize >= out);
74
	ret.resize(out); // shrink to correct size
75
	return ret;
76
}
77
78
bool decode_inplace(std::string_view input, std::span<uint8_t> output)
79
{
80
	size_t out = 0;
81
	auto outSize = output.size();
82
	bool flip = true;
83
	uint8_t tmp = 0;
84
	for (char c : input) {
85
		int d = decode(c);
86
		if (d == -1) continue;
87
		assert(d >= 0);
88
		assert(d <= 15);
89
		if (flip) {
90
			tmp = narrow<uint8_t>(d);
91
		} else {
92
			if (out == outSize) [[unlikely]] return false;
93
			output[out++] = narrow<uint8_t>((tmp << 4) | d);
94
		}
95
		flip = !flip;
96
	}
97
98
	return out == outSize;
99
}
100
101
} // namespace HexDump