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