OXYGENHUB
◆ main openmsx / src / utils / escape_newline.hh
1.7 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef ESCAPE_NEWLINE_HH
2
#define ESCAPE_NEWLINE_HH
3
4
#include "one_of.hh"
5
6
#include <cassert>
7
#include <cstring>
8
#include <string>
9
#include <string_view>
10
11
namespace escape_newline {
12
13
[[nodiscard]] inline std::string encode(std::string_view input)
14
{
15
	std::string result;
16
	result.reserve(input.size());
17
	for (char c : input) {
18
		if (c == one_of('\n', '\\'))  {
19
			if (c == '\n') c = 'n';
20
			result += '\\';
21
		}
22
		result += c;
23
	}
24
	return result;
25
}
26
27
[[nodiscard]] inline std::string decode(std::string_view input)
28
{
29
	std::string result;
30
	result.resize_and_overwrite(input.size(), [&](char* buf, size_t) {
31
		size_t out = 0;
32
		for (size_t i = 0; i < input.size(); ++i) {
33
			char c = input[i];
34
			if (c == '\\') {
35
				if (++i == input.size()) break; // incomplete escape, drop
36
				c = input[i];
37
				if (c == 'n') c = '\n';
38
			}
39
			buf[out++] = c;
40
		}
41
		return out;
42
	});
43
	return result;
44
}
45
46
inline void decode_inplace(std::string& str)
47
{
48
	auto rdPos = str.find('\\');
49
	if (rdPos == std::string::npos) {
50
		// No escapes at all, done
51
		return;
52
	}
53
54
	auto size = str.size();
55
	auto wrPos = rdPos;
56
	do {
57
		assert(rdPos < size);
58
		assert(str[rdPos] == '\\');
59
		if (rdPos + 1 == size) {
60
			// Trailing backslash, shouldn't happen, drop it
61
			break;
62
		}
63
64
		// Decode escape sequence
65
		auto c = str[rdPos + 1];
66
		str[wrPos] = (c == 'n') ? '\n' : c;
67
		rdPos += 2;
68
		wrPos += 1;
69
70
		// Find next backslash
71
		auto next_backslash = str.find('\\', rdPos);
72
73
		// Copy the intermediate non-backslash chunk
74
		auto chunk_end = (next_backslash == std::string::npos) ? size : next_backslash;
75
		auto chunk_len = chunk_end - rdPos;
76
		memmove(&str[wrPos], &str[rdPos], chunk_len);
77
		rdPos += chunk_len;
78
		wrPos += chunk_len;
79
	} while (rdPos < size);
80
81
	str.resize(wrPos);
82
}
83
84
} // namespace escape_newline
85
86
#endif