yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
hex.cc
Go to the documentation of this file.
1#include "hex.h"
2
3#include <cctype>
4#include <limits>
5#include <string>
6
7#include "absl/strings/str_cat.h"
8#include "absl/strings/str_format.h"
9#include "absl/strings/string_view.h"
10
11namespace yaze {
12namespace util {
13
14namespace {
15
16void HandleHexStringParams(std::string& hex, const HexStringParams& params) {
17 switch (params.prefix) {
19 hex = absl::StrCat("$", hex);
20 break;
22 hex = absl::StrCat("#", hex);
23 break;
25 hex = absl::StrCat("0x", hex);
27 default:
28 break;
29 }
30}
31} // namespace
32
33std::string HexByte(uint8_t byte, HexStringParams params) {
34 std::string result;
35 if (params.uppercase) {
36 result = absl::StrFormat("%02X", byte);
37 } else {
38 result = absl::StrFormat("%02x", byte);
39 }
40 HandleHexStringParams(result, params);
41 return result;
42}
43
44std::string HexWord(uint16_t word, HexStringParams params) {
45 std::string result;
46 if (params.uppercase) {
47 result = absl::StrFormat("%04X", word);
48 } else {
49 result = absl::StrFormat("%04x", word);
50 }
51 HandleHexStringParams(result, params);
52 return result;
53}
54
55std::string HexLong(uint32_t dword, HexStringParams params) {
56 std::string result;
57 if (params.uppercase) {
58 result = absl::StrFormat("%06X", dword);
59 } else {
60 result = absl::StrFormat("%06x", dword);
61 }
62 HandleHexStringParams(result, params);
63 return result;
64}
65
66std::string HexLongLong(uint64_t qword, HexStringParams params) {
67 std::string result;
68 if (params.uppercase) {
69 result = absl::StrFormat("%08X", qword);
70 } else {
71 result = absl::StrFormat("%08x", qword);
72 }
73 HandleHexStringParams(result, params);
74 return result;
75}
76
77namespace {
78
79// Parses the whole string as hexadecimal. No sign is accepted: a negative
80// value would wrap into the unsigned result, which is how out-of-range
81// manifest addresses used to load as plausible ones.
82bool ParseHexDigits(absl::string_view str, uint64_t max_value, uint64_t* out) {
83 // Trim surrounding ASCII whitespace, matching the previous strtoul-based
84 // parsers, which skipped leading whitespace.
85 while (!str.empty() &&
86 std::isspace(static_cast<unsigned char>(str.front()))) {
87 str.remove_prefix(1);
88 }
89 while (!str.empty() && std::isspace(static_cast<unsigned char>(str.back()))) {
90 str.remove_suffix(1);
91 }
92
93 if (str.empty()) {
94 return false;
95 }
96 if (str.front() == '$') {
97 str.remove_prefix(1);
98 } else if (str.size() >= 2 && str[0] == '0' &&
99 (str[1] == 'x' || str[1] == 'X')) {
100 str.remove_prefix(2);
101 }
102 if (str.empty()) {
103 return false;
104 }
105
106 uint64_t value = 0;
107 for (const char c : str) {
108 const auto byte = static_cast<unsigned char>(c);
109 if (!std::isxdigit(byte)) {
110 return false;
111 }
112 int digit = 0;
113 if (byte >= '0' && byte <= '9') {
114 digit = byte - '0';
115 } else if (byte >= 'a' && byte <= 'f') {
116 digit = byte - 'a' + 10;
117 } else {
118 digit = byte - 'A' + 10;
119 }
120 // Reject before the shift so the overflow cannot wrap.
121 if (value > (max_value - static_cast<uint64_t>(digit)) / 16) {
122 return false;
123 }
124 value = value * 16 + static_cast<uint64_t>(digit);
125 }
126
127 *out = value;
128 return true;
129}
130
131} // namespace
132
133bool ParseHexString(absl::string_view str, uint64_t* out) {
134 uint64_t value = 0;
135 if (!ParseHexDigits(str, std::numeric_limits<uint64_t>::max(), &value)) {
136 return false;
137 }
138 *out = value;
139 return true;
140}
141
142bool ParseHexString(absl::string_view str, uint32_t* out) {
143 uint64_t value = 0;
144 if (!ParseHexDigits(str, std::numeric_limits<uint32_t>::max(), &value)) {
145 return false;
146 }
147 *out = static_cast<uint32_t>(value);
148 return true;
149}
150
151bool ParseHexString(absl::string_view str, int* out) {
152 uint64_t value = 0;
153 if (!ParseHexDigits(str,
154 static_cast<uint64_t>(std::numeric_limits<int>::max()),
155 &value)) {
156 return false;
157 }
158 *out = static_cast<int>(value);
159 return true;
160}
161
162} // namespace util
163} // namespace yaze
bool ParseHexDigits(absl::string_view str, uint64_t max_value, uint64_t *out)
Definition hex.cc:82
void HandleHexStringParams(std::string &hex, const HexStringParams &params)
Definition hex.cc:16
std::string HexWord(uint16_t word, HexStringParams params)
Definition hex.cc:44
std::string HexByte(uint8_t byte, HexStringParams params)
Definition hex.cc:33
std::string HexLongLong(uint64_t qword, HexStringParams params)
Definition hex.cc:66
bool ParseHexString(absl::string_view str, uint64_t *out)
Definition hex.cc:133
std::string HexLong(uint32_t dword, HexStringParams params)
Definition hex.cc:55
enum yaze::util::HexStringParams::Prefix prefix