1*0b57cec5SDimitry Andric //=== JSON.cpp - JSON value, parsing and serialization - C++ -----------*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===---------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "llvm/Support/JSON.h"
10*0b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h"
11*0b57cec5SDimitry Andric #include "llvm/Support/Format.h"
12*0b57cec5SDimitry Andric #include <cctype>
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric namespace llvm {
15*0b57cec5SDimitry Andric namespace json {
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric Value &Object::operator[](const ObjectKey &K) {
18*0b57cec5SDimitry Andric   return try_emplace(K, nullptr).first->getSecond();
19*0b57cec5SDimitry Andric }
20*0b57cec5SDimitry Andric Value &Object::operator[](ObjectKey &&K) {
21*0b57cec5SDimitry Andric   return try_emplace(std::move(K), nullptr).first->getSecond();
22*0b57cec5SDimitry Andric }
23*0b57cec5SDimitry Andric Value *Object::get(StringRef K) {
24*0b57cec5SDimitry Andric   auto I = find(K);
25*0b57cec5SDimitry Andric   if (I == end())
26*0b57cec5SDimitry Andric     return nullptr;
27*0b57cec5SDimitry Andric   return &I->second;
28*0b57cec5SDimitry Andric }
29*0b57cec5SDimitry Andric const Value *Object::get(StringRef K) const {
30*0b57cec5SDimitry Andric   auto I = find(K);
31*0b57cec5SDimitry Andric   if (I == end())
32*0b57cec5SDimitry Andric     return nullptr;
33*0b57cec5SDimitry Andric   return &I->second;
34*0b57cec5SDimitry Andric }
35*0b57cec5SDimitry Andric llvm::Optional<std::nullptr_t> Object::getNull(StringRef K) const {
36*0b57cec5SDimitry Andric   if (auto *V = get(K))
37*0b57cec5SDimitry Andric     return V->getAsNull();
38*0b57cec5SDimitry Andric   return llvm::None;
39*0b57cec5SDimitry Andric }
40*0b57cec5SDimitry Andric llvm::Optional<bool> Object::getBoolean(StringRef K) const {
41*0b57cec5SDimitry Andric   if (auto *V = get(K))
42*0b57cec5SDimitry Andric     return V->getAsBoolean();
43*0b57cec5SDimitry Andric   return llvm::None;
44*0b57cec5SDimitry Andric }
45*0b57cec5SDimitry Andric llvm::Optional<double> Object::getNumber(StringRef K) const {
46*0b57cec5SDimitry Andric   if (auto *V = get(K))
47*0b57cec5SDimitry Andric     return V->getAsNumber();
48*0b57cec5SDimitry Andric   return llvm::None;
49*0b57cec5SDimitry Andric }
50*0b57cec5SDimitry Andric llvm::Optional<int64_t> Object::getInteger(StringRef K) const {
51*0b57cec5SDimitry Andric   if (auto *V = get(K))
52*0b57cec5SDimitry Andric     return V->getAsInteger();
53*0b57cec5SDimitry Andric   return llvm::None;
54*0b57cec5SDimitry Andric }
55*0b57cec5SDimitry Andric llvm::Optional<llvm::StringRef> Object::getString(StringRef K) const {
56*0b57cec5SDimitry Andric   if (auto *V = get(K))
57*0b57cec5SDimitry Andric     return V->getAsString();
58*0b57cec5SDimitry Andric   return llvm::None;
59*0b57cec5SDimitry Andric }
60*0b57cec5SDimitry Andric const json::Object *Object::getObject(StringRef K) const {
61*0b57cec5SDimitry Andric   if (auto *V = get(K))
62*0b57cec5SDimitry Andric     return V->getAsObject();
63*0b57cec5SDimitry Andric   return nullptr;
64*0b57cec5SDimitry Andric }
65*0b57cec5SDimitry Andric json::Object *Object::getObject(StringRef K) {
66*0b57cec5SDimitry Andric   if (auto *V = get(K))
67*0b57cec5SDimitry Andric     return V->getAsObject();
68*0b57cec5SDimitry Andric   return nullptr;
69*0b57cec5SDimitry Andric }
70*0b57cec5SDimitry Andric const json::Array *Object::getArray(StringRef K) const {
71*0b57cec5SDimitry Andric   if (auto *V = get(K))
72*0b57cec5SDimitry Andric     return V->getAsArray();
73*0b57cec5SDimitry Andric   return nullptr;
74*0b57cec5SDimitry Andric }
75*0b57cec5SDimitry Andric json::Array *Object::getArray(StringRef K) {
76*0b57cec5SDimitry Andric   if (auto *V = get(K))
77*0b57cec5SDimitry Andric     return V->getAsArray();
78*0b57cec5SDimitry Andric   return nullptr;
79*0b57cec5SDimitry Andric }
80*0b57cec5SDimitry Andric bool operator==(const Object &LHS, const Object &RHS) {
81*0b57cec5SDimitry Andric   if (LHS.size() != RHS.size())
82*0b57cec5SDimitry Andric     return false;
83*0b57cec5SDimitry Andric   for (const auto &L : LHS) {
84*0b57cec5SDimitry Andric     auto R = RHS.find(L.first);
85*0b57cec5SDimitry Andric     if (R == RHS.end() || L.second != R->second)
86*0b57cec5SDimitry Andric       return false;
87*0b57cec5SDimitry Andric   }
88*0b57cec5SDimitry Andric   return true;
89*0b57cec5SDimitry Andric }
90*0b57cec5SDimitry Andric 
91*0b57cec5SDimitry Andric Array::Array(std::initializer_list<Value> Elements) {
92*0b57cec5SDimitry Andric   V.reserve(Elements.size());
93*0b57cec5SDimitry Andric   for (const Value &V : Elements) {
94*0b57cec5SDimitry Andric     emplace_back(nullptr);
95*0b57cec5SDimitry Andric     back().moveFrom(std::move(V));
96*0b57cec5SDimitry Andric   }
97*0b57cec5SDimitry Andric }
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric Value::Value(std::initializer_list<Value> Elements)
100*0b57cec5SDimitry Andric     : Value(json::Array(Elements)) {}
101*0b57cec5SDimitry Andric 
102*0b57cec5SDimitry Andric void Value::copyFrom(const Value &M) {
103*0b57cec5SDimitry Andric   Type = M.Type;
104*0b57cec5SDimitry Andric   switch (Type) {
105*0b57cec5SDimitry Andric   case T_Null:
106*0b57cec5SDimitry Andric   case T_Boolean:
107*0b57cec5SDimitry Andric   case T_Double:
108*0b57cec5SDimitry Andric   case T_Integer:
109*0b57cec5SDimitry Andric     memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
110*0b57cec5SDimitry Andric     break;
111*0b57cec5SDimitry Andric   case T_StringRef:
112*0b57cec5SDimitry Andric     create<StringRef>(M.as<StringRef>());
113*0b57cec5SDimitry Andric     break;
114*0b57cec5SDimitry Andric   case T_String:
115*0b57cec5SDimitry Andric     create<std::string>(M.as<std::string>());
116*0b57cec5SDimitry Andric     break;
117*0b57cec5SDimitry Andric   case T_Object:
118*0b57cec5SDimitry Andric     create<json::Object>(M.as<json::Object>());
119*0b57cec5SDimitry Andric     break;
120*0b57cec5SDimitry Andric   case T_Array:
121*0b57cec5SDimitry Andric     create<json::Array>(M.as<json::Array>());
122*0b57cec5SDimitry Andric     break;
123*0b57cec5SDimitry Andric   }
124*0b57cec5SDimitry Andric }
125*0b57cec5SDimitry Andric 
126*0b57cec5SDimitry Andric void Value::moveFrom(const Value &&M) {
127*0b57cec5SDimitry Andric   Type = M.Type;
128*0b57cec5SDimitry Andric   switch (Type) {
129*0b57cec5SDimitry Andric   case T_Null:
130*0b57cec5SDimitry Andric   case T_Boolean:
131*0b57cec5SDimitry Andric   case T_Double:
132*0b57cec5SDimitry Andric   case T_Integer:
133*0b57cec5SDimitry Andric     memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
134*0b57cec5SDimitry Andric     break;
135*0b57cec5SDimitry Andric   case T_StringRef:
136*0b57cec5SDimitry Andric     create<StringRef>(M.as<StringRef>());
137*0b57cec5SDimitry Andric     break;
138*0b57cec5SDimitry Andric   case T_String:
139*0b57cec5SDimitry Andric     create<std::string>(std::move(M.as<std::string>()));
140*0b57cec5SDimitry Andric     M.Type = T_Null;
141*0b57cec5SDimitry Andric     break;
142*0b57cec5SDimitry Andric   case T_Object:
143*0b57cec5SDimitry Andric     create<json::Object>(std::move(M.as<json::Object>()));
144*0b57cec5SDimitry Andric     M.Type = T_Null;
145*0b57cec5SDimitry Andric     break;
146*0b57cec5SDimitry Andric   case T_Array:
147*0b57cec5SDimitry Andric     create<json::Array>(std::move(M.as<json::Array>()));
148*0b57cec5SDimitry Andric     M.Type = T_Null;
149*0b57cec5SDimitry Andric     break;
150*0b57cec5SDimitry Andric   }
151*0b57cec5SDimitry Andric }
152*0b57cec5SDimitry Andric 
153*0b57cec5SDimitry Andric void Value::destroy() {
154*0b57cec5SDimitry Andric   switch (Type) {
155*0b57cec5SDimitry Andric   case T_Null:
156*0b57cec5SDimitry Andric   case T_Boolean:
157*0b57cec5SDimitry Andric   case T_Double:
158*0b57cec5SDimitry Andric   case T_Integer:
159*0b57cec5SDimitry Andric     break;
160*0b57cec5SDimitry Andric   case T_StringRef:
161*0b57cec5SDimitry Andric     as<StringRef>().~StringRef();
162*0b57cec5SDimitry Andric     break;
163*0b57cec5SDimitry Andric   case T_String:
164*0b57cec5SDimitry Andric     as<std::string>().~basic_string();
165*0b57cec5SDimitry Andric     break;
166*0b57cec5SDimitry Andric   case T_Object:
167*0b57cec5SDimitry Andric     as<json::Object>().~Object();
168*0b57cec5SDimitry Andric     break;
169*0b57cec5SDimitry Andric   case T_Array:
170*0b57cec5SDimitry Andric     as<json::Array>().~Array();
171*0b57cec5SDimitry Andric     break;
172*0b57cec5SDimitry Andric   }
173*0b57cec5SDimitry Andric }
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric bool operator==(const Value &L, const Value &R) {
176*0b57cec5SDimitry Andric   if (L.kind() != R.kind())
177*0b57cec5SDimitry Andric     return false;
178*0b57cec5SDimitry Andric   switch (L.kind()) {
179*0b57cec5SDimitry Andric   case Value::Null:
180*0b57cec5SDimitry Andric     return *L.getAsNull() == *R.getAsNull();
181*0b57cec5SDimitry Andric   case Value::Boolean:
182*0b57cec5SDimitry Andric     return *L.getAsBoolean() == *R.getAsBoolean();
183*0b57cec5SDimitry Andric   case Value::Number:
184*0b57cec5SDimitry Andric     // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323
185*0b57cec5SDimitry Andric     // The same integer must convert to the same double, per the standard.
186*0b57cec5SDimitry Andric     // However we see 64-vs-80-bit precision comparisons with gcc-7 -O3 -m32.
187*0b57cec5SDimitry Andric     // So we avoid floating point promotion for exact comparisons.
188*0b57cec5SDimitry Andric     if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
189*0b57cec5SDimitry Andric       return L.getAsInteger() == R.getAsInteger();
190*0b57cec5SDimitry Andric     return *L.getAsNumber() == *R.getAsNumber();
191*0b57cec5SDimitry Andric   case Value::String:
192*0b57cec5SDimitry Andric     return *L.getAsString() == *R.getAsString();
193*0b57cec5SDimitry Andric   case Value::Array:
194*0b57cec5SDimitry Andric     return *L.getAsArray() == *R.getAsArray();
195*0b57cec5SDimitry Andric   case Value::Object:
196*0b57cec5SDimitry Andric     return *L.getAsObject() == *R.getAsObject();
197*0b57cec5SDimitry Andric   }
198*0b57cec5SDimitry Andric   llvm_unreachable("Unknown value kind");
199*0b57cec5SDimitry Andric }
200*0b57cec5SDimitry Andric 
201*0b57cec5SDimitry Andric namespace {
202*0b57cec5SDimitry Andric // Simple recursive-descent JSON parser.
203*0b57cec5SDimitry Andric class Parser {
204*0b57cec5SDimitry Andric public:
205*0b57cec5SDimitry Andric   Parser(StringRef JSON)
206*0b57cec5SDimitry Andric       : Start(JSON.begin()), P(JSON.begin()), End(JSON.end()) {}
207*0b57cec5SDimitry Andric 
208*0b57cec5SDimitry Andric   bool checkUTF8() {
209*0b57cec5SDimitry Andric     size_t ErrOffset;
210*0b57cec5SDimitry Andric     if (isUTF8(StringRef(Start, End - Start), &ErrOffset))
211*0b57cec5SDimitry Andric       return true;
212*0b57cec5SDimitry Andric     P = Start + ErrOffset; // For line/column calculation.
213*0b57cec5SDimitry Andric     return parseError("Invalid UTF-8 sequence");
214*0b57cec5SDimitry Andric   }
215*0b57cec5SDimitry Andric 
216*0b57cec5SDimitry Andric   bool parseValue(Value &Out);
217*0b57cec5SDimitry Andric 
218*0b57cec5SDimitry Andric   bool assertEnd() {
219*0b57cec5SDimitry Andric     eatWhitespace();
220*0b57cec5SDimitry Andric     if (P == End)
221*0b57cec5SDimitry Andric       return true;
222*0b57cec5SDimitry Andric     return parseError("Text after end of document");
223*0b57cec5SDimitry Andric   }
224*0b57cec5SDimitry Andric 
225*0b57cec5SDimitry Andric   Error takeError() {
226*0b57cec5SDimitry Andric     assert(Err);
227*0b57cec5SDimitry Andric     return std::move(*Err);
228*0b57cec5SDimitry Andric   }
229*0b57cec5SDimitry Andric 
230*0b57cec5SDimitry Andric private:
231*0b57cec5SDimitry Andric   void eatWhitespace() {
232*0b57cec5SDimitry Andric     while (P != End && (*P == ' ' || *P == '\r' || *P == '\n' || *P == '\t'))
233*0b57cec5SDimitry Andric       ++P;
234*0b57cec5SDimitry Andric   }
235*0b57cec5SDimitry Andric 
236*0b57cec5SDimitry Andric   // On invalid syntax, parseX() functions return false and set Err.
237*0b57cec5SDimitry Andric   bool parseNumber(char First, Value &Out);
238*0b57cec5SDimitry Andric   bool parseString(std::string &Out);
239*0b57cec5SDimitry Andric   bool parseUnicode(std::string &Out);
240*0b57cec5SDimitry Andric   bool parseError(const char *Msg); // always returns false
241*0b57cec5SDimitry Andric 
242*0b57cec5SDimitry Andric   char next() { return P == End ? 0 : *P++; }
243*0b57cec5SDimitry Andric   char peek() { return P == End ? 0 : *P; }
244*0b57cec5SDimitry Andric   static bool isNumber(char C) {
245*0b57cec5SDimitry Andric     return C == '0' || C == '1' || C == '2' || C == '3' || C == '4' ||
246*0b57cec5SDimitry Andric            C == '5' || C == '6' || C == '7' || C == '8' || C == '9' ||
247*0b57cec5SDimitry Andric            C == 'e' || C == 'E' || C == '+' || C == '-' || C == '.';
248*0b57cec5SDimitry Andric   }
249*0b57cec5SDimitry Andric 
250*0b57cec5SDimitry Andric   Optional<Error> Err;
251*0b57cec5SDimitry Andric   const char *Start, *P, *End;
252*0b57cec5SDimitry Andric };
253*0b57cec5SDimitry Andric 
254*0b57cec5SDimitry Andric bool Parser::parseValue(Value &Out) {
255*0b57cec5SDimitry Andric   eatWhitespace();
256*0b57cec5SDimitry Andric   if (P == End)
257*0b57cec5SDimitry Andric     return parseError("Unexpected EOF");
258*0b57cec5SDimitry Andric   switch (char C = next()) {
259*0b57cec5SDimitry Andric   // Bare null/true/false are easy - first char identifies them.
260*0b57cec5SDimitry Andric   case 'n':
261*0b57cec5SDimitry Andric     Out = nullptr;
262*0b57cec5SDimitry Andric     return (next() == 'u' && next() == 'l' && next() == 'l') ||
263*0b57cec5SDimitry Andric            parseError("Invalid JSON value (null?)");
264*0b57cec5SDimitry Andric   case 't':
265*0b57cec5SDimitry Andric     Out = true;
266*0b57cec5SDimitry Andric     return (next() == 'r' && next() == 'u' && next() == 'e') ||
267*0b57cec5SDimitry Andric            parseError("Invalid JSON value (true?)");
268*0b57cec5SDimitry Andric   case 'f':
269*0b57cec5SDimitry Andric     Out = false;
270*0b57cec5SDimitry Andric     return (next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') ||
271*0b57cec5SDimitry Andric            parseError("Invalid JSON value (false?)");
272*0b57cec5SDimitry Andric   case '"': {
273*0b57cec5SDimitry Andric     std::string S;
274*0b57cec5SDimitry Andric     if (parseString(S)) {
275*0b57cec5SDimitry Andric       Out = std::move(S);
276*0b57cec5SDimitry Andric       return true;
277*0b57cec5SDimitry Andric     }
278*0b57cec5SDimitry Andric     return false;
279*0b57cec5SDimitry Andric   }
280*0b57cec5SDimitry Andric   case '[': {
281*0b57cec5SDimitry Andric     Out = Array{};
282*0b57cec5SDimitry Andric     Array &A = *Out.getAsArray();
283*0b57cec5SDimitry Andric     eatWhitespace();
284*0b57cec5SDimitry Andric     if (peek() == ']') {
285*0b57cec5SDimitry Andric       ++P;
286*0b57cec5SDimitry Andric       return true;
287*0b57cec5SDimitry Andric     }
288*0b57cec5SDimitry Andric     for (;;) {
289*0b57cec5SDimitry Andric       A.emplace_back(nullptr);
290*0b57cec5SDimitry Andric       if (!parseValue(A.back()))
291*0b57cec5SDimitry Andric         return false;
292*0b57cec5SDimitry Andric       eatWhitespace();
293*0b57cec5SDimitry Andric       switch (next()) {
294*0b57cec5SDimitry Andric       case ',':
295*0b57cec5SDimitry Andric         eatWhitespace();
296*0b57cec5SDimitry Andric         continue;
297*0b57cec5SDimitry Andric       case ']':
298*0b57cec5SDimitry Andric         return true;
299*0b57cec5SDimitry Andric       default:
300*0b57cec5SDimitry Andric         return parseError("Expected , or ] after array element");
301*0b57cec5SDimitry Andric       }
302*0b57cec5SDimitry Andric     }
303*0b57cec5SDimitry Andric   }
304*0b57cec5SDimitry Andric   case '{': {
305*0b57cec5SDimitry Andric     Out = Object{};
306*0b57cec5SDimitry Andric     Object &O = *Out.getAsObject();
307*0b57cec5SDimitry Andric     eatWhitespace();
308*0b57cec5SDimitry Andric     if (peek() == '}') {
309*0b57cec5SDimitry Andric       ++P;
310*0b57cec5SDimitry Andric       return true;
311*0b57cec5SDimitry Andric     }
312*0b57cec5SDimitry Andric     for (;;) {
313*0b57cec5SDimitry Andric       if (next() != '"')
314*0b57cec5SDimitry Andric         return parseError("Expected object key");
315*0b57cec5SDimitry Andric       std::string K;
316*0b57cec5SDimitry Andric       if (!parseString(K))
317*0b57cec5SDimitry Andric         return false;
318*0b57cec5SDimitry Andric       eatWhitespace();
319*0b57cec5SDimitry Andric       if (next() != ':')
320*0b57cec5SDimitry Andric         return parseError("Expected : after object key");
321*0b57cec5SDimitry Andric       eatWhitespace();
322*0b57cec5SDimitry Andric       if (!parseValue(O[std::move(K)]))
323*0b57cec5SDimitry Andric         return false;
324*0b57cec5SDimitry Andric       eatWhitespace();
325*0b57cec5SDimitry Andric       switch (next()) {
326*0b57cec5SDimitry Andric       case ',':
327*0b57cec5SDimitry Andric         eatWhitespace();
328*0b57cec5SDimitry Andric         continue;
329*0b57cec5SDimitry Andric       case '}':
330*0b57cec5SDimitry Andric         return true;
331*0b57cec5SDimitry Andric       default:
332*0b57cec5SDimitry Andric         return parseError("Expected , or } after object property");
333*0b57cec5SDimitry Andric       }
334*0b57cec5SDimitry Andric     }
335*0b57cec5SDimitry Andric   }
336*0b57cec5SDimitry Andric   default:
337*0b57cec5SDimitry Andric     if (isNumber(C))
338*0b57cec5SDimitry Andric       return parseNumber(C, Out);
339*0b57cec5SDimitry Andric     return parseError("Invalid JSON value");
340*0b57cec5SDimitry Andric   }
341*0b57cec5SDimitry Andric }
342*0b57cec5SDimitry Andric 
343*0b57cec5SDimitry Andric bool Parser::parseNumber(char First, Value &Out) {
344*0b57cec5SDimitry Andric   // Read the number into a string. (Must be null-terminated for strto*).
345*0b57cec5SDimitry Andric   SmallString<24> S;
346*0b57cec5SDimitry Andric   S.push_back(First);
347*0b57cec5SDimitry Andric   while (isNumber(peek()))
348*0b57cec5SDimitry Andric     S.push_back(next());
349*0b57cec5SDimitry Andric   char *End;
350*0b57cec5SDimitry Andric   // Try first to parse as integer, and if so preserve full 64 bits.
351*0b57cec5SDimitry Andric   // strtoll returns long long >= 64 bits, so check it's in range too.
352*0b57cec5SDimitry Andric   auto I = std::strtoll(S.c_str(), &End, 10);
353*0b57cec5SDimitry Andric   if (End == S.end() && I >= std::numeric_limits<int64_t>::min() &&
354*0b57cec5SDimitry Andric       I <= std::numeric_limits<int64_t>::max()) {
355*0b57cec5SDimitry Andric     Out = int64_t(I);
356*0b57cec5SDimitry Andric     return true;
357*0b57cec5SDimitry Andric   }
358*0b57cec5SDimitry Andric   // If it's not an integer
359*0b57cec5SDimitry Andric   Out = std::strtod(S.c_str(), &End);
360*0b57cec5SDimitry Andric   return End == S.end() || parseError("Invalid JSON value (number?)");
361*0b57cec5SDimitry Andric }
362*0b57cec5SDimitry Andric 
363*0b57cec5SDimitry Andric bool Parser::parseString(std::string &Out) {
364*0b57cec5SDimitry Andric   // leading quote was already consumed.
365*0b57cec5SDimitry Andric   for (char C = next(); C != '"'; C = next()) {
366*0b57cec5SDimitry Andric     if (LLVM_UNLIKELY(P == End))
367*0b57cec5SDimitry Andric       return parseError("Unterminated string");
368*0b57cec5SDimitry Andric     if (LLVM_UNLIKELY((C & 0x1f) == C))
369*0b57cec5SDimitry Andric       return parseError("Control character in string");
370*0b57cec5SDimitry Andric     if (LLVM_LIKELY(C != '\\')) {
371*0b57cec5SDimitry Andric       Out.push_back(C);
372*0b57cec5SDimitry Andric       continue;
373*0b57cec5SDimitry Andric     }
374*0b57cec5SDimitry Andric     // Handle escape sequence.
375*0b57cec5SDimitry Andric     switch (C = next()) {
376*0b57cec5SDimitry Andric     case '"':
377*0b57cec5SDimitry Andric     case '\\':
378*0b57cec5SDimitry Andric     case '/':
379*0b57cec5SDimitry Andric       Out.push_back(C);
380*0b57cec5SDimitry Andric       break;
381*0b57cec5SDimitry Andric     case 'b':
382*0b57cec5SDimitry Andric       Out.push_back('\b');
383*0b57cec5SDimitry Andric       break;
384*0b57cec5SDimitry Andric     case 'f':
385*0b57cec5SDimitry Andric       Out.push_back('\f');
386*0b57cec5SDimitry Andric       break;
387*0b57cec5SDimitry Andric     case 'n':
388*0b57cec5SDimitry Andric       Out.push_back('\n');
389*0b57cec5SDimitry Andric       break;
390*0b57cec5SDimitry Andric     case 'r':
391*0b57cec5SDimitry Andric       Out.push_back('\r');
392*0b57cec5SDimitry Andric       break;
393*0b57cec5SDimitry Andric     case 't':
394*0b57cec5SDimitry Andric       Out.push_back('\t');
395*0b57cec5SDimitry Andric       break;
396*0b57cec5SDimitry Andric     case 'u':
397*0b57cec5SDimitry Andric       if (!parseUnicode(Out))
398*0b57cec5SDimitry Andric         return false;
399*0b57cec5SDimitry Andric       break;
400*0b57cec5SDimitry Andric     default:
401*0b57cec5SDimitry Andric       return parseError("Invalid escape sequence");
402*0b57cec5SDimitry Andric     }
403*0b57cec5SDimitry Andric   }
404*0b57cec5SDimitry Andric   return true;
405*0b57cec5SDimitry Andric }
406*0b57cec5SDimitry Andric 
407*0b57cec5SDimitry Andric static void encodeUtf8(uint32_t Rune, std::string &Out) {
408*0b57cec5SDimitry Andric   if (Rune < 0x80) {
409*0b57cec5SDimitry Andric     Out.push_back(Rune & 0x7F);
410*0b57cec5SDimitry Andric   } else if (Rune < 0x800) {
411*0b57cec5SDimitry Andric     uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
412*0b57cec5SDimitry Andric     uint8_t SecondByte = 0x80 | (Rune & 0x3F);
413*0b57cec5SDimitry Andric     Out.push_back(FirstByte);
414*0b57cec5SDimitry Andric     Out.push_back(SecondByte);
415*0b57cec5SDimitry Andric   } else if (Rune < 0x10000) {
416*0b57cec5SDimitry Andric     uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
417*0b57cec5SDimitry Andric     uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
418*0b57cec5SDimitry Andric     uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
419*0b57cec5SDimitry Andric     Out.push_back(FirstByte);
420*0b57cec5SDimitry Andric     Out.push_back(SecondByte);
421*0b57cec5SDimitry Andric     Out.push_back(ThirdByte);
422*0b57cec5SDimitry Andric   } else if (Rune < 0x110000) {
423*0b57cec5SDimitry Andric     uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
424*0b57cec5SDimitry Andric     uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
425*0b57cec5SDimitry Andric     uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
426*0b57cec5SDimitry Andric     uint8_t FourthByte = 0x80 | (Rune & 0x3F);
427*0b57cec5SDimitry Andric     Out.push_back(FirstByte);
428*0b57cec5SDimitry Andric     Out.push_back(SecondByte);
429*0b57cec5SDimitry Andric     Out.push_back(ThirdByte);
430*0b57cec5SDimitry Andric     Out.push_back(FourthByte);
431*0b57cec5SDimitry Andric   } else {
432*0b57cec5SDimitry Andric     llvm_unreachable("Invalid codepoint");
433*0b57cec5SDimitry Andric   }
434*0b57cec5SDimitry Andric }
435*0b57cec5SDimitry Andric 
436*0b57cec5SDimitry Andric // Parse a UTF-16 \uNNNN escape sequence. "\u" has already been consumed.
437*0b57cec5SDimitry Andric // May parse several sequential escapes to ensure proper surrogate handling.
438*0b57cec5SDimitry Andric // We do not use ConvertUTF.h, it can't accept and replace unpaired surrogates.
439*0b57cec5SDimitry Andric // These are invalid Unicode but valid JSON (RFC 8259, section 8.2).
440*0b57cec5SDimitry Andric bool Parser::parseUnicode(std::string &Out) {
441*0b57cec5SDimitry Andric   // Invalid UTF is not a JSON error (RFC 8529§8.2). It gets replaced by U+FFFD.
442*0b57cec5SDimitry Andric   auto Invalid = [&] { Out.append(/* UTF-8 */ {'\xef', '\xbf', '\xbd'}); };
443*0b57cec5SDimitry Andric   // Decodes 4 hex digits from the stream into Out, returns false on error.
444*0b57cec5SDimitry Andric   auto Parse4Hex = [this](uint16_t &Out) -> bool {
445*0b57cec5SDimitry Andric     Out = 0;
446*0b57cec5SDimitry Andric     char Bytes[] = {next(), next(), next(), next()};
447*0b57cec5SDimitry Andric     for (unsigned char C : Bytes) {
448*0b57cec5SDimitry Andric       if (!std::isxdigit(C))
449*0b57cec5SDimitry Andric         return parseError("Invalid \\u escape sequence");
450*0b57cec5SDimitry Andric       Out <<= 4;
451*0b57cec5SDimitry Andric       Out |= (C > '9') ? (C & ~0x20) - 'A' + 10 : (C - '0');
452*0b57cec5SDimitry Andric     }
453*0b57cec5SDimitry Andric     return true;
454*0b57cec5SDimitry Andric   };
455*0b57cec5SDimitry Andric   uint16_t First; // UTF-16 code unit from the first \u escape.
456*0b57cec5SDimitry Andric   if (!Parse4Hex(First))
457*0b57cec5SDimitry Andric     return false;
458*0b57cec5SDimitry Andric 
459*0b57cec5SDimitry Andric   // We loop to allow proper surrogate-pair error handling.
460*0b57cec5SDimitry Andric   while (true) {
461*0b57cec5SDimitry Andric     // Case 1: the UTF-16 code unit is already a codepoint in the BMP.
462*0b57cec5SDimitry Andric     if (LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) {
463*0b57cec5SDimitry Andric       encodeUtf8(First, Out);
464*0b57cec5SDimitry Andric       return true;
465*0b57cec5SDimitry Andric     }
466*0b57cec5SDimitry Andric 
467*0b57cec5SDimitry Andric     // Case 2: it's an (unpaired) trailing surrogate.
468*0b57cec5SDimitry Andric     if (LLVM_UNLIKELY(First >= 0xDC00)) {
469*0b57cec5SDimitry Andric       Invalid();
470*0b57cec5SDimitry Andric       return true;
471*0b57cec5SDimitry Andric     }
472*0b57cec5SDimitry Andric 
473*0b57cec5SDimitry Andric     // Case 3: it's a leading surrogate. We expect a trailing one next.
474*0b57cec5SDimitry Andric     // Case 3a: there's no trailing \u escape. Don't advance in the stream.
475*0b57cec5SDimitry Andric     if (LLVM_UNLIKELY(P + 2 > End || *P != '\\' || *(P + 1) != 'u')) {
476*0b57cec5SDimitry Andric       Invalid(); // Leading surrogate was unpaired.
477*0b57cec5SDimitry Andric       return true;
478*0b57cec5SDimitry Andric     }
479*0b57cec5SDimitry Andric     P += 2;
480*0b57cec5SDimitry Andric     uint16_t Second;
481*0b57cec5SDimitry Andric     if (!Parse4Hex(Second))
482*0b57cec5SDimitry Andric       return false;
483*0b57cec5SDimitry Andric     // Case 3b: there was another \u escape, but it wasn't a trailing surrogate.
484*0b57cec5SDimitry Andric     if (LLVM_UNLIKELY(Second < 0xDC00 || Second >= 0xE000)) {
485*0b57cec5SDimitry Andric       Invalid();      // Leading surrogate was unpaired.
486*0b57cec5SDimitry Andric       First = Second; // Second escape still needs to be processed.
487*0b57cec5SDimitry Andric       continue;
488*0b57cec5SDimitry Andric     }
489*0b57cec5SDimitry Andric     // Case 3c: a valid surrogate pair encoding an astral codepoint.
490*0b57cec5SDimitry Andric     encodeUtf8(0x10000 | ((First - 0xD800) << 10) | (Second - 0xDC00), Out);
491*0b57cec5SDimitry Andric     return true;
492*0b57cec5SDimitry Andric   }
493*0b57cec5SDimitry Andric }
494*0b57cec5SDimitry Andric 
495*0b57cec5SDimitry Andric bool Parser::parseError(const char *Msg) {
496*0b57cec5SDimitry Andric   int Line = 1;
497*0b57cec5SDimitry Andric   const char *StartOfLine = Start;
498*0b57cec5SDimitry Andric   for (const char *X = Start; X < P; ++X) {
499*0b57cec5SDimitry Andric     if (*X == 0x0A) {
500*0b57cec5SDimitry Andric       ++Line;
501*0b57cec5SDimitry Andric       StartOfLine = X + 1;
502*0b57cec5SDimitry Andric     }
503*0b57cec5SDimitry Andric   }
504*0b57cec5SDimitry Andric   Err.emplace(
505*0b57cec5SDimitry Andric       llvm::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start));
506*0b57cec5SDimitry Andric   return false;
507*0b57cec5SDimitry Andric }
508*0b57cec5SDimitry Andric } // namespace
509*0b57cec5SDimitry Andric 
510*0b57cec5SDimitry Andric Expected<Value> parse(StringRef JSON) {
511*0b57cec5SDimitry Andric   Parser P(JSON);
512*0b57cec5SDimitry Andric   Value E = nullptr;
513*0b57cec5SDimitry Andric   if (P.checkUTF8())
514*0b57cec5SDimitry Andric     if (P.parseValue(E))
515*0b57cec5SDimitry Andric       if (P.assertEnd())
516*0b57cec5SDimitry Andric         return std::move(E);
517*0b57cec5SDimitry Andric   return P.takeError();
518*0b57cec5SDimitry Andric }
519*0b57cec5SDimitry Andric char ParseError::ID = 0;
520*0b57cec5SDimitry Andric 
521*0b57cec5SDimitry Andric static std::vector<const Object::value_type *> sortedElements(const Object &O) {
522*0b57cec5SDimitry Andric   std::vector<const Object::value_type *> Elements;
523*0b57cec5SDimitry Andric   for (const auto &E : O)
524*0b57cec5SDimitry Andric     Elements.push_back(&E);
525*0b57cec5SDimitry Andric   llvm::sort(Elements,
526*0b57cec5SDimitry Andric              [](const Object::value_type *L, const Object::value_type *R) {
527*0b57cec5SDimitry Andric                return L->first < R->first;
528*0b57cec5SDimitry Andric              });
529*0b57cec5SDimitry Andric   return Elements;
530*0b57cec5SDimitry Andric }
531*0b57cec5SDimitry Andric 
532*0b57cec5SDimitry Andric bool isUTF8(llvm::StringRef S, size_t *ErrOffset) {
533*0b57cec5SDimitry Andric   // Fast-path for ASCII, which is valid UTF-8.
534*0b57cec5SDimitry Andric   if (LLVM_LIKELY(isASCII(S)))
535*0b57cec5SDimitry Andric     return true;
536*0b57cec5SDimitry Andric 
537*0b57cec5SDimitry Andric   const UTF8 *Data = reinterpret_cast<const UTF8 *>(S.data()), *Rest = Data;
538*0b57cec5SDimitry Andric   if (LLVM_LIKELY(isLegalUTF8String(&Rest, Data + S.size())))
539*0b57cec5SDimitry Andric     return true;
540*0b57cec5SDimitry Andric 
541*0b57cec5SDimitry Andric   if (ErrOffset)
542*0b57cec5SDimitry Andric     *ErrOffset = Rest - Data;
543*0b57cec5SDimitry Andric   return false;
544*0b57cec5SDimitry Andric }
545*0b57cec5SDimitry Andric 
546*0b57cec5SDimitry Andric std::string fixUTF8(llvm::StringRef S) {
547*0b57cec5SDimitry Andric   // This isn't particularly efficient, but is only for error-recovery.
548*0b57cec5SDimitry Andric   std::vector<UTF32> Codepoints(S.size()); // 1 codepoint per byte suffices.
549*0b57cec5SDimitry Andric   const UTF8 *In8 = reinterpret_cast<const UTF8 *>(S.data());
550*0b57cec5SDimitry Andric   UTF32 *Out32 = Codepoints.data();
551*0b57cec5SDimitry Andric   ConvertUTF8toUTF32(&In8, In8 + S.size(), &Out32, Out32 + Codepoints.size(),
552*0b57cec5SDimitry Andric                      lenientConversion);
553*0b57cec5SDimitry Andric   Codepoints.resize(Out32 - Codepoints.data());
554*0b57cec5SDimitry Andric   std::string Res(4 * Codepoints.size(), 0); // 4 bytes per codepoint suffice
555*0b57cec5SDimitry Andric   const UTF32 *In32 = Codepoints.data();
556*0b57cec5SDimitry Andric   UTF8 *Out8 = reinterpret_cast<UTF8 *>(&Res[0]);
557*0b57cec5SDimitry Andric   ConvertUTF32toUTF8(&In32, In32 + Codepoints.size(), &Out8, Out8 + Res.size(),
558*0b57cec5SDimitry Andric                      strictConversion);
559*0b57cec5SDimitry Andric   Res.resize(reinterpret_cast<char *>(Out8) - Res.data());
560*0b57cec5SDimitry Andric   return Res;
561*0b57cec5SDimitry Andric }
562*0b57cec5SDimitry Andric 
563*0b57cec5SDimitry Andric static void quote(llvm::raw_ostream &OS, llvm::StringRef S) {
564*0b57cec5SDimitry Andric   OS << '\"';
565*0b57cec5SDimitry Andric   for (unsigned char C : S) {
566*0b57cec5SDimitry Andric     if (C == 0x22 || C == 0x5C)
567*0b57cec5SDimitry Andric       OS << '\\';
568*0b57cec5SDimitry Andric     if (C >= 0x20) {
569*0b57cec5SDimitry Andric       OS << C;
570*0b57cec5SDimitry Andric       continue;
571*0b57cec5SDimitry Andric     }
572*0b57cec5SDimitry Andric     OS << '\\';
573*0b57cec5SDimitry Andric     switch (C) {
574*0b57cec5SDimitry Andric     // A few characters are common enough to make short escapes worthwhile.
575*0b57cec5SDimitry Andric     case '\t':
576*0b57cec5SDimitry Andric       OS << 't';
577*0b57cec5SDimitry Andric       break;
578*0b57cec5SDimitry Andric     case '\n':
579*0b57cec5SDimitry Andric       OS << 'n';
580*0b57cec5SDimitry Andric       break;
581*0b57cec5SDimitry Andric     case '\r':
582*0b57cec5SDimitry Andric       OS << 'r';
583*0b57cec5SDimitry Andric       break;
584*0b57cec5SDimitry Andric     default:
585*0b57cec5SDimitry Andric       OS << 'u';
586*0b57cec5SDimitry Andric       llvm::write_hex(OS, C, llvm::HexPrintStyle::Lower, 4);
587*0b57cec5SDimitry Andric       break;
588*0b57cec5SDimitry Andric     }
589*0b57cec5SDimitry Andric   }
590*0b57cec5SDimitry Andric   OS << '\"';
591*0b57cec5SDimitry Andric }
592*0b57cec5SDimitry Andric 
593*0b57cec5SDimitry Andric void llvm::json::OStream::value(const Value &V) {
594*0b57cec5SDimitry Andric   switch (V.kind()) {
595*0b57cec5SDimitry Andric   case Value::Null:
596*0b57cec5SDimitry Andric     valueBegin();
597*0b57cec5SDimitry Andric     OS << "null";
598*0b57cec5SDimitry Andric     return;
599*0b57cec5SDimitry Andric   case Value::Boolean:
600*0b57cec5SDimitry Andric     valueBegin();
601*0b57cec5SDimitry Andric     OS << (*V.getAsBoolean() ? "true" : "false");
602*0b57cec5SDimitry Andric     return;
603*0b57cec5SDimitry Andric   case Value::Number:
604*0b57cec5SDimitry Andric     valueBegin();
605*0b57cec5SDimitry Andric     if (V.Type == Value::T_Integer)
606*0b57cec5SDimitry Andric       OS << *V.getAsInteger();
607*0b57cec5SDimitry Andric     else
608*0b57cec5SDimitry Andric       OS << format("%.*g", std::numeric_limits<double>::max_digits10,
609*0b57cec5SDimitry Andric                    *V.getAsNumber());
610*0b57cec5SDimitry Andric     return;
611*0b57cec5SDimitry Andric   case Value::String:
612*0b57cec5SDimitry Andric     valueBegin();
613*0b57cec5SDimitry Andric     quote(OS, *V.getAsString());
614*0b57cec5SDimitry Andric     return;
615*0b57cec5SDimitry Andric   case Value::Array:
616*0b57cec5SDimitry Andric     return array([&] {
617*0b57cec5SDimitry Andric       for (const Value &E : *V.getAsArray())
618*0b57cec5SDimitry Andric         value(E);
619*0b57cec5SDimitry Andric     });
620*0b57cec5SDimitry Andric   case Value::Object:
621*0b57cec5SDimitry Andric     return object([&] {
622*0b57cec5SDimitry Andric       for (const Object::value_type *E : sortedElements(*V.getAsObject()))
623*0b57cec5SDimitry Andric         attribute(E->first, E->second);
624*0b57cec5SDimitry Andric     });
625*0b57cec5SDimitry Andric   }
626*0b57cec5SDimitry Andric }
627*0b57cec5SDimitry Andric 
628*0b57cec5SDimitry Andric void llvm::json::OStream::valueBegin() {
629*0b57cec5SDimitry Andric   assert(Stack.back().Ctx != Object && "Only attributes allowed here");
630*0b57cec5SDimitry Andric   if (Stack.back().HasValue) {
631*0b57cec5SDimitry Andric     assert(Stack.back().Ctx != Singleton && "Only one value allowed here");
632*0b57cec5SDimitry Andric     OS << ',';
633*0b57cec5SDimitry Andric   }
634*0b57cec5SDimitry Andric   if (Stack.back().Ctx == Array)
635*0b57cec5SDimitry Andric     newline();
636*0b57cec5SDimitry Andric   Stack.back().HasValue = true;
637*0b57cec5SDimitry Andric }
638*0b57cec5SDimitry Andric 
639*0b57cec5SDimitry Andric void llvm::json::OStream::newline() {
640*0b57cec5SDimitry Andric   if (IndentSize) {
641*0b57cec5SDimitry Andric     OS.write('\n');
642*0b57cec5SDimitry Andric     OS.indent(Indent);
643*0b57cec5SDimitry Andric   }
644*0b57cec5SDimitry Andric }
645*0b57cec5SDimitry Andric 
646*0b57cec5SDimitry Andric void llvm::json::OStream::arrayBegin() {
647*0b57cec5SDimitry Andric   valueBegin();
648*0b57cec5SDimitry Andric   Stack.emplace_back();
649*0b57cec5SDimitry Andric   Stack.back().Ctx = Array;
650*0b57cec5SDimitry Andric   Indent += IndentSize;
651*0b57cec5SDimitry Andric   OS << '[';
652*0b57cec5SDimitry Andric }
653*0b57cec5SDimitry Andric 
654*0b57cec5SDimitry Andric void llvm::json::OStream::arrayEnd() {
655*0b57cec5SDimitry Andric   assert(Stack.back().Ctx == Array);
656*0b57cec5SDimitry Andric   Indent -= IndentSize;
657*0b57cec5SDimitry Andric   if (Stack.back().HasValue)
658*0b57cec5SDimitry Andric     newline();
659*0b57cec5SDimitry Andric   OS << ']';
660*0b57cec5SDimitry Andric   Stack.pop_back();
661*0b57cec5SDimitry Andric   assert(!Stack.empty());
662*0b57cec5SDimitry Andric }
663*0b57cec5SDimitry Andric 
664*0b57cec5SDimitry Andric void llvm::json::OStream::objectBegin() {
665*0b57cec5SDimitry Andric   valueBegin();
666*0b57cec5SDimitry Andric   Stack.emplace_back();
667*0b57cec5SDimitry Andric   Stack.back().Ctx = Object;
668*0b57cec5SDimitry Andric   Indent += IndentSize;
669*0b57cec5SDimitry Andric   OS << '{';
670*0b57cec5SDimitry Andric }
671*0b57cec5SDimitry Andric 
672*0b57cec5SDimitry Andric void llvm::json::OStream::objectEnd() {
673*0b57cec5SDimitry Andric   assert(Stack.back().Ctx == Object);
674*0b57cec5SDimitry Andric   Indent -= IndentSize;
675*0b57cec5SDimitry Andric   if (Stack.back().HasValue)
676*0b57cec5SDimitry Andric     newline();
677*0b57cec5SDimitry Andric   OS << '}';
678*0b57cec5SDimitry Andric   Stack.pop_back();
679*0b57cec5SDimitry Andric   assert(!Stack.empty());
680*0b57cec5SDimitry Andric }
681*0b57cec5SDimitry Andric 
682*0b57cec5SDimitry Andric void llvm::json::OStream::attributeBegin(llvm::StringRef Key) {
683*0b57cec5SDimitry Andric   assert(Stack.back().Ctx == Object);
684*0b57cec5SDimitry Andric   if (Stack.back().HasValue)
685*0b57cec5SDimitry Andric     OS << ',';
686*0b57cec5SDimitry Andric   newline();
687*0b57cec5SDimitry Andric   Stack.back().HasValue = true;
688*0b57cec5SDimitry Andric   Stack.emplace_back();
689*0b57cec5SDimitry Andric   Stack.back().Ctx = Singleton;
690*0b57cec5SDimitry Andric   if (LLVM_LIKELY(isUTF8(Key))) {
691*0b57cec5SDimitry Andric     quote(OS, Key);
692*0b57cec5SDimitry Andric   } else {
693*0b57cec5SDimitry Andric     assert(false && "Invalid UTF-8 in attribute key");
694*0b57cec5SDimitry Andric     quote(OS, fixUTF8(Key));
695*0b57cec5SDimitry Andric   }
696*0b57cec5SDimitry Andric   OS.write(':');
697*0b57cec5SDimitry Andric   if (IndentSize)
698*0b57cec5SDimitry Andric     OS.write(' ');
699*0b57cec5SDimitry Andric }
700*0b57cec5SDimitry Andric 
701*0b57cec5SDimitry Andric void llvm::json::OStream::attributeEnd() {
702*0b57cec5SDimitry Andric   assert(Stack.back().Ctx == Singleton);
703*0b57cec5SDimitry Andric   assert(Stack.back().HasValue && "Attribute must have a value");
704*0b57cec5SDimitry Andric   Stack.pop_back();
705*0b57cec5SDimitry Andric   assert(Stack.back().Ctx == Object);
706*0b57cec5SDimitry Andric }
707*0b57cec5SDimitry Andric 
708*0b57cec5SDimitry Andric } // namespace json
709*0b57cec5SDimitry Andric } // namespace llvm
710*0b57cec5SDimitry Andric 
711*0b57cec5SDimitry Andric void llvm::format_provider<llvm::json::Value>::format(
712*0b57cec5SDimitry Andric     const llvm::json::Value &E, raw_ostream &OS, StringRef Options) {
713*0b57cec5SDimitry Andric   unsigned IndentAmount = 0;
714*0b57cec5SDimitry Andric   if (!Options.empty() && Options.getAsInteger(/*Radix=*/10, IndentAmount))
715*0b57cec5SDimitry Andric     llvm_unreachable("json::Value format options should be an integer");
716*0b57cec5SDimitry Andric   json::OStream(OS, IndentAmount).value(E);
717*0b57cec5SDimitry Andric }
718*0b57cec5SDimitry Andric 
719