1 #include "json_utils.h"
2
3 namespace node {
4
EscapeJsonChars(std::string_view str)5 std::string EscapeJsonChars(std::string_view str) {
6 // 'static constexpr' is slightly better than static const
7 // since the initialization occurs at compile time.
8 // See https://lemire.me/blog/I3Cah
9 static constexpr std::string_view control_symbols[0x20] = {
10 "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005",
11 "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\u000b",
12 "\\f", "\\r", "\\u000e", "\\u000f", "\\u0010", "\\u0011",
13 "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017",
14 "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d",
15 "\\u001e", "\\u001f"};
16
17 std::string ret;
18 size_t last_pos = 0;
19 size_t pos = 0;
20 for (; pos < str.size(); ++pos) {
21 std::string replace;
22 char ch = str[pos];
23 if (ch == '\\') {
24 replace = "\\\\";
25 } else if (ch == '\"') {
26 replace = "\\\"";
27 } else {
28 size_t num = static_cast<size_t>(ch);
29 if (num < 0x20) replace = control_symbols[num];
30 }
31 if (!replace.empty()) {
32 if (pos > last_pos) {
33 ret += str.substr(last_pos, pos - last_pos);
34 }
35 last_pos = pos + 1;
36 ret += replace;
37 }
38 }
39 // Append any remaining symbols.
40 if (last_pos < str.size()) {
41 ret += str.substr(last_pos, pos - last_pos);
42 }
43 return ret;
44 }
45
Reindent(const std::string & str,int indent_depth)46 std::string Reindent(const std::string& str, int indent_depth) {
47 if (indent_depth <= 0) return str;
48 const std::string indent(indent_depth, ' ');
49 std::string out;
50 std::string::size_type pos = 0;
51 for (;;) {
52 std::string::size_type prev_pos = pos;
53 pos = str.find('\n', pos);
54
55 out.append(indent);
56
57 if (pos == std::string::npos) {
58 out.append(str, prev_pos, std::string::npos);
59 break;
60 } else {
61 pos++;
62 out.append(str, prev_pos, pos - prev_pos);
63 }
64 }
65
66 return out;
67 }
68
69 } // namespace node
70