Torch
Loading...
Searching...
No Matches
BKEmitText.h
1#pragma once
2
3#include <cctype>
4#include <cstdint>
5#include <cstdio>
6#include <iomanip>
7#include <string>
8#include <yaml-cpp/yaml.h>
9
10// Shared yaml/text emission formatters
11#define YAML_HEX(num) YAML::Hex << (num) << YAML::Dec
12#define FORMAT_HEX(x, w) \
13 std::hex << std::uppercase << std::setfill('0') << std::setw(w) << x << std::nouppercase << std::dec
14
15namespace BK64 {
16
17// Emit a text string for modding yaml.
18inline void EmitText(YAML::Emitter& out, const std::string& str) {
19 const char* s = str.c_str();
20 bool plain = true;
21 for (const char* p = s; *p != '\0'; p++) {
22 if (static_cast<uint8_t>(*p) < 0x20 || static_cast<uint8_t>(*p) > 0x7E || *p == '\\') {
23 plain = false;
24 break;
25 }
26 }
27 if (plain) {
28 out << YAML::DoubleQuoted << s;
29 return;
30 }
31 std::string escaped;
32 for (const char* p = s; *p != '\0'; p++) {
33 const auto c = static_cast<uint8_t>(*p);
34 if (c == '\\') {
35 escaped += "\\\\";
36 } else if (c < 0x20 || c > 0x7E) {
37 char buf[5];
38 std::snprintf(buf, sizeof(buf), "\\x%02X", c);
39 escaped += buf;
40 } else {
41 escaped += static_cast<char>(c);
42 }
43 }
44 out << YAML::SingleQuoted << escaped;
45}
46
47// Reverse EmitText's escapes on a string read back from modding yaml.
48inline std::string DecodeText(const std::string& str) {
49 std::string out;
50 out.reserve(str.size());
51 for (size_t i = 0; i < str.size(); i++) {
52 if (str[i] == '\\' && i + 1 < str.size()) {
53 if (str[i + 1] == '\\') {
54 out += '\\';
55 i++;
56 continue;
57 }
58 if ((str[i + 1] == 'x' || str[i + 1] == 'X') && i + 3 < str.size() &&
59 std::isxdigit(static_cast<unsigned char>(str[i + 2])) &&
60 std::isxdigit(static_cast<unsigned char>(str[i + 3]))) {
61 out += static_cast<char>(std::stoi(str.substr(i + 2, 2), nullptr, 16));
62 i += 3;
63 continue;
64 }
65 }
66 out += str[i];
67 }
68 return out;
69}
70
71} // namespace BK64