Skip to content

Commit f284d59

Browse files
addaleaxtargos
authored andcommitted
src: move JSONWriter into its own file
The JSONWriter feature is not inherently related to the report feature in any way. As a drive-by fix, remove a number of unused header includes. PR-URL: #32552 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Richard Lau <[email protected]>
1 parent e066584 commit f284d59

7 files changed

+238
-225
lines changed

node.gyp

+3-1
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@
560560
'src/js_native_api_v8.h',
561561
'src/js_native_api_v8_internals.h',
562562
'src/js_stream.cc',
563+
'src/json_utils.cc',
563564
'src/module_wrap.cc',
564565
'src/node.cc',
565566
'src/node_api.cc',
@@ -644,6 +645,7 @@
644645
'src/histogram.h',
645646
'src/histogram-inl.h',
646647
'src/js_stream.h',
648+
'src/json_utils.h',
647649
'src/large_pages/node_large_page.cc',
648650
'src/large_pages/node_large_page.h',
649651
'src/memory_tracker.h',
@@ -1141,7 +1143,7 @@
11411143
'test/cctest/test_linked_binding.cc',
11421144
'test/cctest/test_per_process.cc',
11431145
'test/cctest/test_platform.cc',
1144-
'test/cctest/test_report_util.cc',
1146+
'test/cctest/test_json_utils.cc',
11451147
'test/cctest/test_sockaddr.cc',
11461148
'test/cctest/test_traced_value.cc',
11471149
'test/cctest/test_util.cc',

src/json_utils.cc

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

src/json_utils.h

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#ifndef SRC_JSON_UTILS_H_
2+
#define SRC_JSON_UTILS_H_
3+
4+
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5+
6+
#include <iomanip>
7+
#include <ostream>
8+
#include <limits>
9+
10+
namespace node {
11+
12+
std::string EscapeJsonChars(const std::string& str);
13+
std::string Reindent(const std::string& str, int indentation);
14+
15+
// JSON compiler definitions.
16+
class JSONWriter {
17+
public:
18+
JSONWriter(std::ostream& out, bool compact)
19+
: out_(out), compact_(compact) {}
20+
21+
private:
22+
inline void indent() { indent_ += 2; }
23+
inline void deindent() { indent_ -= 2; }
24+
inline void advance() {
25+
if (compact_) return;
26+
for (int i = 0; i < indent_; i++) out_ << ' ';
27+
}
28+
inline void write_one_space() {
29+
if (compact_) return;
30+
out_ << ' ';
31+
}
32+
inline void write_new_line() {
33+
if (compact_) return;
34+
out_ << '\n';
35+
}
36+
37+
public:
38+
inline void json_start() {
39+
if (state_ == kAfterValue) out_ << ',';
40+
write_new_line();
41+
advance();
42+
out_ << '{';
43+
indent();
44+
state_ = kObjectStart;
45+
}
46+
47+
inline void json_end() {
48+
write_new_line();
49+
deindent();
50+
advance();
51+
out_ << '}';
52+
state_ = kAfterValue;
53+
}
54+
template <typename T>
55+
inline void json_objectstart(T key) {
56+
if (state_ == kAfterValue) out_ << ',';
57+
write_new_line();
58+
advance();
59+
write_string(key);
60+
out_ << ':';
61+
write_one_space();
62+
out_ << '{';
63+
indent();
64+
state_ = kObjectStart;
65+
}
66+
67+
template <typename T>
68+
inline void json_arraystart(T key) {
69+
if (state_ == kAfterValue) out_ << ',';
70+
write_new_line();
71+
advance();
72+
write_string(key);
73+
out_ << ':';
74+
write_one_space();
75+
out_ << '[';
76+
indent();
77+
state_ = kObjectStart;
78+
}
79+
inline void json_objectend() {
80+
write_new_line();
81+
deindent();
82+
advance();
83+
out_ << '}';
84+
if (indent_ == 0) {
85+
// Top-level object is complete, so end the line.
86+
out_ << '\n';
87+
}
88+
state_ = kAfterValue;
89+
}
90+
91+
inline void json_arrayend() {
92+
write_new_line();
93+
deindent();
94+
advance();
95+
out_ << ']';
96+
state_ = kAfterValue;
97+
}
98+
template <typename T, typename U>
99+
inline void json_keyvalue(const T& key, const U& value) {
100+
if (state_ == kAfterValue) out_ << ',';
101+
write_new_line();
102+
advance();
103+
write_string(key);
104+
out_ << ':';
105+
write_one_space();
106+
write_value(value);
107+
state_ = kAfterValue;
108+
}
109+
110+
template <typename U>
111+
inline void json_element(const U& value) {
112+
if (state_ == kAfterValue) out_ << ',';
113+
write_new_line();
114+
advance();
115+
write_value(value);
116+
state_ = kAfterValue;
117+
}
118+
119+
struct Null {}; // Usable as a JSON value.
120+
121+
struct ForeignJSON {
122+
std::string as_string;
123+
};
124+
125+
private:
126+
template <typename T,
127+
typename test_for_number = typename std::
128+
enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
129+
inline void write_value(T number) {
130+
if (std::is_same<T, bool>::value)
131+
out_ << (number ? "true" : "false");
132+
else
133+
out_ << number;
134+
}
135+
136+
inline void write_value(Null null) { out_ << "null"; }
137+
inline void write_value(const char* str) { write_string(str); }
138+
inline void write_value(const std::string& str) { write_string(str); }
139+
140+
inline void write_value(const ForeignJSON& json) {
141+
out_ << Reindent(json.as_string, indent_);
142+
}
143+
144+
inline void write_string(const std::string& str) {
145+
out_ << '"' << EscapeJsonChars(str) << '"';
146+
}
147+
inline void write_string(const char* str) { write_string(std::string(str)); }
148+
149+
enum JSONState { kObjectStart, kAfterValue };
150+
std::ostream& out_;
151+
bool compact_;
152+
int indent_ = 0;
153+
int state_ = kObjectStart;
154+
};
155+
156+
} // namespace node
157+
158+
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
159+
160+
#endif // SRC_JSON_UTILS_H_

src/node_report.cc

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "env-inl.h"
2+
#include "json_utils.h"
23
#include "node_report.h"
34
#include "debug_utils-inl.h"
45
#include "diagnosticfilename-inl.h"
@@ -16,6 +17,7 @@
1617
#include <dlfcn.h>
1718
#endif
1819

20+
#include <iostream>
1921
#include <cstring>
2022
#include <ctime>
2123
#include <cwctype>
@@ -30,6 +32,7 @@ using node::arraysize;
3032
using node::ConditionVariable;
3133
using node::DiagnosticFilename;
3234
using node::Environment;
35+
using node::JSONWriter;
3336
using node::Mutex;
3437
using node::NativeSymbolDebuggingContext;
3538
using node::TIME_TYPE;

0 commit comments

Comments
 (0)