LLVM 22.0.0git
JSON.cpp
Go to the documentation of this file.
1//=== JSON.cpp - JSON value, parsing and serialization - C++ -----------*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===---------------------------------------------------------------------===//
8
9#include "llvm/Support/JSON.h"
10#include "llvm/ADT/STLExtras.h"
13#include "llvm/Support/Error.h"
14#include "llvm/Support/Format.h"
17#include <cctype>
18#include <cerrno>
19#include <optional>
20
21namespace llvm {
22namespace json {
23
25 return try_emplace(K, nullptr).first->getSecond();
26}
28 return try_emplace(std::move(K), nullptr).first->getSecond();
29}
31 auto I = find(K);
32 if (I == end())
33 return nullptr;
34 return &I->second;
35}
36const Value *Object::get(StringRef K) const {
37 auto I = find(K);
38 if (I == end())
39 return nullptr;
40 return &I->second;
41}
42std::optional<std::nullptr_t> Object::getNull(StringRef K) const {
43 if (auto *V = get(K))
44 return V->getAsNull();
45 return std::nullopt;
46}
47std::optional<bool> Object::getBoolean(StringRef K) const {
48 if (auto *V = get(K))
49 return V->getAsBoolean();
50 return std::nullopt;
51}
52std::optional<double> Object::getNumber(StringRef K) const {
53 if (auto *V = get(K))
54 return V->getAsNumber();
55 return std::nullopt;
56}
57std::optional<int64_t> Object::getInteger(StringRef K) const {
58 if (auto *V = get(K))
59 return V->getAsInteger();
60 return std::nullopt;
61}
62std::optional<llvm::StringRef> Object::getString(StringRef K) const {
63 if (auto *V = get(K))
64 return V->getAsString();
65 return std::nullopt;
66}
68 if (auto *V = get(K))
69 return V->getAsObject();
70 return nullptr;
71}
73 if (auto *V = get(K))
74 return V->getAsObject();
75 return nullptr;
76}
78 if (auto *V = get(K))
79 return V->getAsArray();
80 return nullptr;
81}
83 if (auto *V = get(K))
84 return V->getAsArray();
85 return nullptr;
86}
87bool operator==(const Object &LHS, const Object &RHS) { return LHS.M == RHS.M; }
88
89Array::Array(std::initializer_list<Value> Elements) {
90 V.reserve(Elements.size());
91 for (const Value &V : Elements) {
92 emplace_back(nullptr);
93 back().moveFrom(std::move(V));
94 }
95}
96
97Value::Value(std::initializer_list<Value> Elements)
98 : Value(json::Array(Elements)) {}
99
100void Value::copyFrom(const Value &M) {
101 Type = M.Type;
102 switch (Type) {
103 case T_Null:
104 case T_Boolean:
105 case T_Double:
106 case T_Integer:
107 case T_UINT64:
108 memcpy(&Union, &M.Union, sizeof(Union));
109 break;
110 case T_StringRef:
111 create<StringRef>(M.as<StringRef>());
112 break;
113 case T_String:
114 create<std::string>(M.as<std::string>());
115 break;
116 case T_Object:
117 create<json::Object>(M.as<json::Object>());
118 break;
119 case T_Array:
120 create<json::Array>(M.as<json::Array>());
121 break;
122 }
123}
124
125void Value::moveFrom(const Value &&M) {
126 Type = M.Type;
127 switch (Type) {
128 case T_Null:
129 case T_Boolean:
130 case T_Double:
131 case T_Integer:
132 case T_UINT64:
133 memcpy(&Union, &M.Union, sizeof(Union));
134 break;
135 case T_StringRef:
136 create<StringRef>(M.as<StringRef>());
137 break;
138 case T_String:
139 create<std::string>(std::move(M.as<std::string>()));
140 M.Type = T_Null;
141 break;
142 case T_Object:
143 create<json::Object>(std::move(M.as<json::Object>()));
144 M.Type = T_Null;
145 break;
146 case T_Array:
147 create<json::Array>(std::move(M.as<json::Array>()));
148 M.Type = T_Null;
149 break;
150 }
151}
152
153void Value::destroy() {
154 switch (Type) {
155 case T_Null:
156 case T_Boolean:
157 case T_Double:
158 case T_Integer:
159 case T_UINT64:
160 break;
161 case T_StringRef:
162 as<StringRef>().~StringRef();
163 break;
164 case T_String:
165 as<std::string>().~basic_string();
166 break;
167 case T_Object:
168 as<json::Object>().~Object();
169 break;
170 case T_Array:
171 as<json::Array>().~Array();
172 break;
173 }
174}
175
176void Value::print(llvm::raw_ostream &OS) const { OS << *this; }
177
178bool operator==(const Value &L, const Value &R) {
179 if (L.kind() != R.kind())
180 return false;
181 switch (L.kind()) {
182 case Value::Null:
183 return *L.getAsNull() == *R.getAsNull();
184 case Value::Boolean:
185 return *L.getAsBoolean() == *R.getAsBoolean();
186 case Value::Number:
187 // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323
188 // The same integer must convert to the same double, per the standard.
189 // However we see 64-vs-80-bit precision comparisons with gcc-7 -O3 -m32.
190 // So we avoid floating point promotion for exact comparisons.
191 if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
192 return L.getAsInteger() == R.getAsInteger();
193 return *L.getAsNumber() == *R.getAsNumber();
194 case Value::String:
195 return *L.getAsString() == *R.getAsString();
196 case Value::Array:
197 return *L.getAsArray() == *R.getAsArray();
198 case Value::Object:
199 return *L.getAsObject() == *R.getAsObject();
200 }
201 llvm_unreachable("Unknown value kind");
202}
203
205 // Walk up to the root context, and count the number of segments.
206 unsigned Count = 0;
207 const Path *P;
208 for (P = this; P->Parent != nullptr; P = P->Parent)
209 ++Count;
210 Path::Root *R = P->Seg.root();
211 // Fill in the error message and copy the path (in reverse order).
212 R->ErrorMessage = Msg;
213 R->ErrorPath.resize(Count);
214 auto It = R->ErrorPath.begin();
215 for (P = this; P->Parent != nullptr; P = P->Parent)
216 *It++ = P->Seg;
217}
218
220 std::string S;
221 raw_string_ostream OS(S);
222 OS << (ErrorMessage.empty() ? "invalid JSON contents" : ErrorMessage);
223 if (ErrorPath.empty()) {
224 if (!Name.empty())
225 OS << " when parsing " << Name;
226 } else {
227 OS << " at " << (Name.empty() ? "(root)" : Name);
228 for (const Path::Segment &S : llvm::reverse(ErrorPath)) {
229 if (S.isField())
230 OS << '.' << S.field();
231 else
232 OS << '[' << S.index() << ']';
233 }
234 }
236}
237
238std::vector<const Object::value_type *> sortedElements(const Object &O) {
239 std::vector<const Object::value_type *> Elements;
240 for (const auto &E : O)
241 Elements.push_back(&E);
242 llvm::sort(Elements,
243 [](const Object::value_type *L, const Object::value_type *R) {
244 return L->first < R->first;
245 });
246 return Elements;
247}
248
249// Prints a one-line version of a value that isn't our main focus.
250// We interleave writes to OS and JOS, exploiting the lack of extra buffering.
251// This is OK as we own the implementation.
252static void abbreviate(const Value &V, OStream &JOS) {
253 switch (V.kind()) {
254 case Value::Array:
255 JOS.rawValue(V.getAsArray()->empty() ? "[]" : "[ ... ]");
256 break;
257 case Value::Object:
258 JOS.rawValue(V.getAsObject()->empty() ? "{}" : "{ ... }");
259 break;
260 case Value::String: {
261 llvm::StringRef S = *V.getAsString();
262 if (S.size() < 40) {
263 JOS.value(V);
264 } else {
265 std::string Truncated = fixUTF8(S.take_front(37));
266 Truncated.append("...");
267 JOS.value(Truncated);
268 }
269 break;
270 }
271 default:
272 JOS.value(V);
273 }
274}
275
276// Prints a semi-expanded version of a value that is our main focus.
277// Array/Object entries are printed, but not recursively as they may be huge.
278static void abbreviateChildren(const Value &V, OStream &JOS) {
279 switch (V.kind()) {
280 case Value::Array:
281 JOS.array([&] {
282 for (const auto &I : *V.getAsArray())
283 abbreviate(I, JOS);
284 });
285 break;
286 case Value::Object:
287 JOS.object([&] {
288 for (const auto *KV : sortedElements(*V.getAsObject())) {
289 JOS.attributeBegin(KV->first);
290 abbreviate(KV->second, JOS);
291 JOS.attributeEnd();
292 }
293 });
294 break;
295 default:
296 JOS.value(V);
297 }
298}
299
301 OStream JOS(OS, /*IndentSize=*/2);
302 // PrintValue recurses down the path, printing the ancestors of our target.
303 // Siblings of nodes along the path are printed with abbreviate(), and the
304 // target itself is printed with the somewhat richer abbreviateChildren().
305 // 'Recurse' is the lambda itself, to allow recursive calls.
306 auto PrintValue = [&](const Value &V, ArrayRef<Segment> Path, auto &Recurse) {
307 // Print the target node itself, with the error as a comment.
308 // Also used if we can't follow our path, e.g. it names a field that
309 // *should* exist but doesn't.
310 auto HighlightCurrent = [&] {
311 std::string Comment = "error: ";
312 Comment.append(ErrorMessage.data(), ErrorMessage.size());
313 JOS.comment(Comment);
314 abbreviateChildren(V, JOS);
315 };
316 if (Path.empty()) // We reached our target.
317 return HighlightCurrent();
318 const Segment &S = Path.back(); // Path is in reverse order.
319 if (S.isField()) {
320 // Current node is an object, path names a field.
321 llvm::StringRef FieldName = S.field();
322 const Object *O = V.getAsObject();
323 if (!O || !O->get(FieldName))
324 return HighlightCurrent();
325 JOS.object([&] {
326 for (const auto *KV : sortedElements(*O)) {
327 JOS.attributeBegin(KV->first);
328 if (FieldName == StringRef(KV->first))
329 Recurse(KV->second, Path.drop_back(), Recurse);
330 else
331 abbreviate(KV->second, JOS);
332 JOS.attributeEnd();
333 }
334 });
335 } else {
336 // Current node is an array, path names an element.
337 const Array *A = V.getAsArray();
338 if (!A || S.index() >= A->size())
339 return HighlightCurrent();
340 JOS.array([&] {
341 unsigned Current = 0;
342 for (const auto &V : *A) {
343 if (Current++ == S.index())
344 Recurse(V, Path.drop_back(), Recurse);
345 else
346 abbreviate(V, JOS);
347 }
348 });
349 }
350 };
351 PrintValue(R, ErrorPath, PrintValue);
352}
353
354namespace {
355// Simple recursive-descent JSON parser.
356class Parser {
357public:
358 Parser(StringRef JSON)
359 : Start(JSON.begin()), P(JSON.begin()), End(JSON.end()) {}
360
361 bool checkUTF8() {
362 size_t ErrOffset;
363 if (isUTF8(StringRef(Start, End - Start), &ErrOffset))
364 return true;
365 P = Start + ErrOffset; // For line/column calculation.
366 return parseError("Invalid UTF-8 sequence");
367 }
368
369 bool parseValue(Value &Out);
370
371 bool assertEnd() {
372 eatWhitespace();
373 if (P == End)
374 return true;
375 return parseError("Text after end of document");
376 }
377
378 Error takeError() {
379 assert(Err);
380 return std::move(*Err);
381 }
382
383private:
384 void eatWhitespace() {
385 while (P != End && (*P == ' ' || *P == '\r' || *P == '\n' || *P == '\t'))
386 ++P;
387 }
388
389 // On invalid syntax, parseX() functions return false and set Err.
390 bool parseNumber(char First, Value &Out);
391 bool parseString(std::string &Out);
392 bool parseUnicode(std::string &Out);
393 bool parseError(const char *Msg); // always returns false
394
395 char next() { return P == End ? 0 : *P++; }
396 char peek() { return P == End ? 0 : *P; }
397 static bool isNumber(char C) {
398 return C == '0' || C == '1' || C == '2' || C == '3' || C == '4' ||
399 C == '5' || C == '6' || C == '7' || C == '8' || C == '9' ||
400 C == 'e' || C == 'E' || C == '+' || C == '-' || C == '.';
401 }
402
403 std::optional<Error> Err;
404 const char *Start, *P, *End;
405};
406} // namespace
407
408bool Parser::parseValue(Value &Out) {
409 eatWhitespace();
410 if (P == End)
411 return parseError("Unexpected EOF");
412 switch (char C = next()) {
413 // Bare null/true/false are easy - first char identifies them.
414 case 'n':
415 Out = nullptr;
416 return (next() == 'u' && next() == 'l' && next() == 'l') ||
417 parseError("Invalid JSON value (null?)");
418 case 't':
419 Out = true;
420 return (next() == 'r' && next() == 'u' && next() == 'e') ||
421 parseError("Invalid JSON value (true?)");
422 case 'f':
423 Out = false;
424 return (next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') ||
425 parseError("Invalid JSON value (false?)");
426 case '"': {
427 std::string S;
428 if (parseString(S)) {
429 Out = std::move(S);
430 return true;
431 }
432 return false;
433 }
434 case '[': {
435 Out = Array{};
436 Array &A = *Out.getAsArray();
437 eatWhitespace();
438 if (peek() == ']') {
439 ++P;
440 return true;
441 }
442 for (;;) {
443 A.emplace_back(nullptr);
444 if (!parseValue(A.back()))
445 return false;
446 eatWhitespace();
447 switch (next()) {
448 case ',':
449 eatWhitespace();
450 continue;
451 case ']':
452 return true;
453 default:
454 return parseError("Expected , or ] after array element");
455 }
456 }
457 }
458 case '{': {
459 Out = Object{};
460 Object &O = *Out.getAsObject();
461 eatWhitespace();
462 if (peek() == '}') {
463 ++P;
464 return true;
465 }
466 for (;;) {
467 if (next() != '"')
468 return parseError("Expected object key");
469 std::string K;
470 if (!parseString(K))
471 return false;
472 eatWhitespace();
473 if (next() != ':')
474 return parseError("Expected : after object key");
475 eatWhitespace();
476 if (!parseValue(O[std::move(K)]))
477 return false;
478 eatWhitespace();
479 switch (next()) {
480 case ',':
481 eatWhitespace();
482 continue;
483 case '}':
484 return true;
485 default:
486 return parseError("Expected , or } after object property");
487 }
488 }
489 }
490 default:
491 if (isNumber(C))
492 return parseNumber(C, Out);
493 return parseError("Invalid JSON value");
494 }
495}
496
497bool Parser::parseNumber(char First, Value &Out) {
498 // Read the number into a string. (Must be null-terminated for strto*).
499 SmallString<24> S;
500 S.push_back(First);
501 while (isNumber(peek()))
502 S.push_back(next());
503 char *End;
504 // Try first to parse as integer, and if so preserve full 64 bits.
505 // We check for errno for out of bounds errors and for End == S.end()
506 // to make sure that the numeric string is not malformed.
507 errno = 0;
508 int64_t I = std::strtoll(S.c_str(), &End, 10);
509 if (End == S.end() && errno != ERANGE) {
510 Out = I;
511 return true;
512 }
513 // strtroull has a special handling for negative numbers, but in this
514 // case we don't want to do that because negative numbers were already
515 // handled in the previous block.
516 if (First != '-') {
517 errno = 0;
518 uint64_t UI = std::strtoull(S.c_str(), &End, 10);
519 if (End == S.end() && errno != ERANGE) {
520 Out = UI;
521 return true;
522 }
523 }
524 // If it's not an integer
525 Out = std::strtod(S.c_str(), &End);
526 return End == S.end() || parseError("Invalid JSON value (number?)");
527}
528
529bool Parser::parseString(std::string &Out) {
530 // leading quote was already consumed.
531 for (char C = next(); C != '"'; C = next()) {
532 if (LLVM_UNLIKELY(P == End))
533 return parseError("Unterminated string");
534 if (LLVM_UNLIKELY((C & 0x1f) == C))
535 return parseError("Control character in string");
536 if (LLVM_LIKELY(C != '\\')) {
537 Out.push_back(C);
538 continue;
539 }
540 // Handle escape sequence.
541 switch (C = next()) {
542 case '"':
543 case '\\':
544 case '/':
545 Out.push_back(C);
546 break;
547 case 'b':
548 Out.push_back('\b');
549 break;
550 case 'f':
551 Out.push_back('\f');
552 break;
553 case 'n':
554 Out.push_back('\n');
555 break;
556 case 'r':
557 Out.push_back('\r');
558 break;
559 case 't':
560 Out.push_back('\t');
561 break;
562 case 'u':
563 if (!parseUnicode(Out))
564 return false;
565 break;
566 default:
567 return parseError("Invalid escape sequence");
568 }
569 }
570 return true;
571}
572
573static void encodeUtf8(uint32_t Rune, std::string &Out) {
574 if (Rune < 0x80) {
575 Out.push_back(Rune & 0x7F);
576 } else if (Rune < 0x800) {
577 uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
578 uint8_t SecondByte = 0x80 | (Rune & 0x3F);
579 Out.push_back(FirstByte);
580 Out.push_back(SecondByte);
581 } else if (Rune < 0x10000) {
582 uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
583 uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
584 uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
585 Out.push_back(FirstByte);
586 Out.push_back(SecondByte);
587 Out.push_back(ThirdByte);
588 } else if (Rune < 0x110000) {
589 uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
590 uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
591 uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
592 uint8_t FourthByte = 0x80 | (Rune & 0x3F);
593 Out.push_back(FirstByte);
594 Out.push_back(SecondByte);
595 Out.push_back(ThirdByte);
596 Out.push_back(FourthByte);
597 } else {
598 llvm_unreachable("Invalid codepoint");
599 }
600}
601
602// Parse a UTF-16 \uNNNN escape sequence. "\u" has already been consumed.
603// May parse several sequential escapes to ensure proper surrogate handling.
604// We do not use ConvertUTF.h, it can't accept and replace unpaired surrogates.
605// These are invalid Unicode but valid JSON (RFC 8259, section 8.2).
606bool Parser::parseUnicode(std::string &Out) {
607 // Invalid UTF is not a JSON error (RFC 8529§8.2). It gets replaced by U+FFFD.
608 auto Invalid = [&] { Out.append(/* UTF-8 */ {'\xef', '\xbf', '\xbd'}); };
609 // Decodes 4 hex digits from the stream into Out, returns false on error.
610 auto Parse4Hex = [this](uint16_t &Out) -> bool {
611 Out = 0;
612 char Bytes[] = {next(), next(), next(), next()};
613 for (unsigned char C : Bytes) {
614 if (!std::isxdigit(C))
615 return parseError("Invalid \\u escape sequence");
616 Out <<= 4;
617 Out |= (C > '9') ? (C & ~0x20) - 'A' + 10 : (C - '0');
618 }
619 return true;
620 };
621 uint16_t First; // UTF-16 code unit from the first \u escape.
622 if (!Parse4Hex(First))
623 return false;
624
625 // We loop to allow proper surrogate-pair error handling.
626 while (true) {
627 // Case 1: the UTF-16 code unit is already a codepoint in the BMP.
629 encodeUtf8(First, Out);
630 return true;
631 }
632
633 // Case 2: it's an (unpaired) trailing surrogate.
634 if (LLVM_UNLIKELY(First >= 0xDC00)) {
635 Invalid();
636 return true;
637 }
638
639 // Case 3: it's a leading surrogate. We expect a trailing one next.
640 // Case 3a: there's no trailing \u escape. Don't advance in the stream.
641 if (LLVM_UNLIKELY(P + 2 > End || *P != '\\' || *(P + 1) != 'u')) {
642 Invalid(); // Leading surrogate was unpaired.
643 return true;
644 }
645 P += 2;
646 uint16_t Second;
647 if (!Parse4Hex(Second))
648 return false;
649 // Case 3b: there was another \u escape, but it wasn't a trailing surrogate.
650 if (LLVM_UNLIKELY(Second < 0xDC00 || Second >= 0xE000)) {
651 Invalid(); // Leading surrogate was unpaired.
652 First = Second; // Second escape still needs to be processed.
653 continue;
654 }
655 // Case 3c: a valid surrogate pair encoding an astral codepoint.
656 encodeUtf8(0x10000 | ((First - 0xD800) << 10) | (Second - 0xDC00), Out);
657 return true;
658 }
659}
660
661bool Parser::parseError(const char *Msg) {
662 int Line = 1;
663 const char *StartOfLine = Start;
664 for (const char *X = Start; X < P; ++X) {
665 if (*X == 0x0A) {
666 ++Line;
667 StartOfLine = X + 1;
668 }
669 }
670 Err.emplace(
671 std::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start));
672 return false;
673}
674
676 Parser P(JSON);
677 Value E = nullptr;
678 if (P.checkUTF8())
679 if (P.parseValue(E))
680 if (P.assertEnd())
681 return std::move(E);
682 return P.takeError();
683}
684char ParseError::ID = 0;
685
686bool isUTF8(llvm::StringRef S, size_t *ErrOffset) {
687 // Fast-path for ASCII, which is valid UTF-8.
688 if (LLVM_LIKELY(isASCII(S)))
689 return true;
690
691 const UTF8 *Data = reinterpret_cast<const UTF8 *>(S.data()), *Rest = Data;
692 if (LLVM_LIKELY(isLegalUTF8String(&Rest, Data + S.size())))
693 return true;
694
695 if (ErrOffset)
696 *ErrOffset = Rest - Data;
697 return false;
698}
699
700std::string fixUTF8(llvm::StringRef S) {
701 // This isn't particularly efficient, but is only for error-recovery.
702 std::vector<UTF32> Codepoints(S.size()); // 1 codepoint per byte suffices.
703 const UTF8 *In8 = reinterpret_cast<const UTF8 *>(S.data());
704 UTF32 *Out32 = Codepoints.data();
705 ConvertUTF8toUTF32(&In8, In8 + S.size(), &Out32, Out32 + Codepoints.size(),
707 Codepoints.resize(Out32 - Codepoints.data());
708 std::string Res(4 * Codepoints.size(), 0); // 4 bytes per codepoint suffice
709 const UTF32 *In32 = Codepoints.data();
710 UTF8 *Out8 = reinterpret_cast<UTF8 *>(&Res[0]);
711 ConvertUTF32toUTF8(&In32, In32 + Codepoints.size(), &Out8, Out8 + Res.size(),
713 Res.resize(reinterpret_cast<char *>(Out8) - Res.data());
714 return Res;
715}
716
718 OS << '\"';
719 for (unsigned char C : S) {
720 if (C == 0x22 || C == 0x5C)
721 OS << '\\';
722 if (C >= 0x20) {
723 OS << C;
724 continue;
725 }
726 OS << '\\';
727 switch (C) {
728 // A few characters are common enough to make short escapes worthwhile.
729 case '\t':
730 OS << 't';
731 break;
732 case '\n':
733 OS << 'n';
734 break;
735 case '\r':
736 OS << 'r';
737 break;
738 default:
739 OS << 'u';
741 break;
742 }
743 }
744 OS << '\"';
745}
746
748 switch (V.kind()) {
749 case Value::Null:
750 valueBegin();
751 OS << "null";
752 return;
753 case Value::Boolean:
754 valueBegin();
755 OS << (*V.getAsBoolean() ? "true" : "false");
756 return;
757 case Value::Number:
758 valueBegin();
759 if (V.Type == Value::T_Integer)
760 OS << *V.getAsInteger();
761 else if (V.Type == Value::T_UINT64)
762 OS << *V.getAsUINT64();
763 else
764 OS << format("%.*g", std::numeric_limits<double>::max_digits10,
765 *V.getAsNumber());
766 return;
767 case Value::String:
768 valueBegin();
769 quote(OS, *V.getAsString());
770 return;
771 case Value::Array:
772 return array([&] {
773 for (const Value &E : *V.getAsArray())
774 value(E);
775 });
776 case Value::Object:
777 return object([&] {
778 for (const Object::value_type *E : sortedElements(*V.getAsObject()))
779 attribute(E->first, E->second);
780 });
781 }
782}
783
784void llvm::json::OStream::valueBegin() {
785 assert(Stack.back().Ctx != Object && "Only attributes allowed here");
786 if (Stack.back().HasValue) {
787 assert(Stack.back().Ctx != Singleton && "Only one value allowed here");
788 OS << ',';
789 }
790 if (Stack.back().Ctx == Array)
791 newline();
792 flushComment();
793 Stack.back().HasValue = true;
794}
795
797 assert(PendingComment.empty() && "Only one comment per value!");
798 PendingComment = Comment;
799}
800
801void OStream::flushComment() {
802 if (PendingComment.empty())
803 return;
804 OS << (IndentSize ? "/* " : "/*");
805 // Be sure not to accidentally emit "*/". Transform to "* /".
806 while (!PendingComment.empty()) {
807 auto Pos = PendingComment.find("*/");
808 if (Pos == StringRef::npos) {
809 OS << PendingComment;
810 PendingComment = "";
811 } else {
812 OS << PendingComment.take_front(Pos) << "* /";
813 PendingComment = PendingComment.drop_front(Pos + 2);
814 }
815 }
816 OS << (IndentSize ? " */" : "*/");
817 // Comments are on their own line unless attached to an attribute value.
818 if (Stack.size() > 1 && Stack.back().Ctx == Singleton) {
819 if (IndentSize)
820 OS << ' ';
821 } else {
822 newline();
823 }
824}
825
826void llvm::json::OStream::newline() {
827 if (IndentSize) {
828 OS.write('\n');
829 OS.indent(Indent);
830 }
831}
832
834 valueBegin();
835 Stack.emplace_back();
836 Stack.back().Ctx = Array;
837 Indent += IndentSize;
838 OS << '[';
839}
840
842 assert(Stack.back().Ctx == Array);
843 Indent -= IndentSize;
844 if (Stack.back().HasValue)
845 newline();
846 OS << ']';
847 assert(PendingComment.empty());
848 Stack.pop_back();
849 assert(!Stack.empty());
850}
851
853 valueBegin();
854 Stack.emplace_back();
855 Stack.back().Ctx = Object;
856 Indent += IndentSize;
857 OS << '{';
858}
859
861 assert(Stack.back().Ctx == Object);
862 Indent -= IndentSize;
863 if (Stack.back().HasValue)
864 newline();
865 OS << '}';
866 assert(PendingComment.empty());
867 Stack.pop_back();
868 assert(!Stack.empty());
869}
870
872 assert(Stack.back().Ctx == Object);
873 if (Stack.back().HasValue)
874 OS << ',';
875 newline();
876 flushComment();
877 Stack.back().HasValue = true;
878 Stack.emplace_back();
879 Stack.back().Ctx = Singleton;
880 if (LLVM_LIKELY(isUTF8(Key))) {
881 quote(OS, Key);
882 } else {
883 assert(false && "Invalid UTF-8 in attribute key");
884 quote(OS, fixUTF8(Key));
885 }
886 OS.write(':');
887 if (IndentSize)
888 OS.write(' ');
889}
890
892 assert(Stack.back().Ctx == Singleton);
893 assert(Stack.back().HasValue && "Attribute must have a value");
894 assert(PendingComment.empty());
895 Stack.pop_back();
896 assert(Stack.back().Ctx == Object);
897}
898
900 valueBegin();
901 Stack.emplace_back();
902 Stack.back().Ctx = RawValue;
903 return OS;
904}
905
907 assert(Stack.back().Ctx == RawValue);
908 Stack.pop_back();
909}
910
911} // namespace json
912} // namespace llvm
913
916 unsigned IndentAmount = 0;
917 if (!Options.empty() && Options.getAsInteger(/*Radix=*/10, IndentAmount))
918 llvm_unreachable("json::Value format options should be an integer");
919 json::OStream(OS, IndentAmount).value(E);
920}
921
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:336
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:335
This file supports working with JSON data.
static LVOptions Options
Definition LVOptions.cpp:25
#define I(x, y, z)
Definition MD5.cpp:58
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static bool peek(struct InternalInstruction *insn, uint8_t &byte)
Value * RHS
Value * LHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:862
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:154
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:148
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition StringRef.h:590
static constexpr size_t npos
Definition StringRef.h:57
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
Type(LLVMContext &C, TypeID tid)
Definition Type.h:93
LLVM Value Representation.
Definition Value.h:75
An Array is a JSON array, which contains heterogeneous JSON values.
Definition JSON.h:166
void emplace_back(Args &&...A)
Definition JSON.h:564
Value & back()
Definition JSON.h:547
json::OStream allows writing well-formed JSON without materializing all structures as json::Value ahe...
Definition JSON.h:998
void object(Block Contents)
Emit an object whose elements are emitted in the provided Block.
Definition JSON.h:1028
void rawValue(llvm::function_ref< void(raw_ostream &)> Contents)
Emit an externally-serialized value.
Definition JSON.h:1036
LLVM_ABI void attributeBegin(llvm::StringRef Key)
Definition JSON.cpp:871
void attribute(llvm::StringRef Key, const Value &Contents)
Emit an attribute whose value is self-contained (number, vector<int> etc).
Definition JSON.h:1053
LLVM_ABI void arrayBegin()
Definition JSON.cpp:833
LLVM_ABI void objectBegin()
Definition JSON.cpp:852
LLVM_ABI raw_ostream & rawValueBegin()
Definition JSON.cpp:899
LLVM_ABI void comment(llvm::StringRef)
Emit a JavaScript comment associated with the next printed value.
Definition JSON.cpp:796
void array(Block Contents)
Emit an array whose elements are emitted in the provided Block.
Definition JSON.h:1022
LLVM_ABI void arrayEnd()
Definition JSON.cpp:841
LLVM_ABI void attributeEnd()
Definition JSON.cpp:891
LLVM_ABI void value(const Value &V)
Emit a self-contained value (number, string, vector<string> etc).
Definition JSON.cpp:747
LLVM_ABI void rawValueEnd()
Definition JSON.cpp:906
LLVM_ABI void objectEnd()
Definition JSON.cpp:860
ObjectKey is a used to capture keys in Object.
Definition JSON.h:588
An Object is a JSON object, which maps strings to heterogenous JSON values.
Definition JSON.h:98
iterator end()
Definition JSON.h:117
LLVM_ABI std::optional< bool > getBoolean(StringRef K) const
Definition JSON.cpp:47
LLVM_ABI Value & operator[](const ObjectKey &K)
Definition JSON.cpp:24
LLVM_ABI std::optional< double > getNumber(StringRef K) const
Definition JSON.cpp:52
LLVM_ABI const json::Object * getObject(StringRef K) const
Definition JSON.cpp:67
LLVM_ABI std::optional< llvm::StringRef > getString(StringRef K) const
Definition JSON.cpp:62
Storage::value_type value_type
Definition JSON.h:105
LLVM_ABI Value * get(StringRef K)
Definition JSON.cpp:30
LLVM_ABI std::optional< int64_t > getInteger(StringRef K) const
Definition JSON.cpp:57
LLVM_ABI std::optional< std::nullptr_t > getNull(StringRef K) const
Definition JSON.cpp:42
std::pair< iterator, bool > try_emplace(const ObjectKey &K, Ts &&... Args)
Definition JSON.h:126
iterator find(StringRef K)
Definition JSON.h:136
LLVM_ABI const json::Array * getArray(StringRef K) const
Definition JSON.cpp:77
static LLVM_ABI char ID
Definition JSON.h:919
The root is the trivial Path to the root value.
Definition JSON.h:713
LLVM_ABI void printErrorContext(const Value &, llvm::raw_ostream &) const
Print the root value with the error shown inline as a comment.
Definition JSON.cpp:300
LLVM_ABI Error getError() const
Returns the last error reported, or else a generic error.
Definition JSON.cpp:219
LLVM_ABI void report(llvm::StringLiteral Message)
Records that the value at the current path is invalid.
Definition JSON.cpp:204
Path(Root &R)
The root may be treated as a Path.
Definition JSON.h:676
A Value is an JSON value of unknown type.
Definition JSON.h:290
friend class Object
Definition JSON.h:493
LLVM_ABI void print(llvm::raw_ostream &OS) const
Definition JSON.cpp:176
Value(const Value &M)
Definition JSON.h:304
@ Number
Number values can store both int64s and doubles at full precision, depending on what they were constr...
Definition JSON.h:297
friend class Array
Definition JSON.h:492
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
static void abbreviateChildren(const Value &V, OStream &JOS)
Definition JSON.cpp:278
LLVM_ABI llvm::Expected< Value > parse(llvm::StringRef JSON)
Parses the provided JSON source, or returns a ParseError.
Definition JSON.cpp:675
static void abbreviate(const Value &V, OStream &JOS)
Definition JSON.cpp:252
LLVM_ABI bool operator==(const Object &LHS, const Object &RHS)
Definition JSON.cpp:87
LLVM_ABI bool isUTF8(llvm::StringRef S, size_t *ErrOffset=nullptr)
Returns true if S is valid UTF-8, which is required for use as JSON.
Definition JSON.cpp:686
LLVM_ABI std::vector< const Object::value_type * > sortedElements(const Object &O)
Definition JSON.cpp:238
static void quote(llvm::raw_ostream &OS, llvm::StringRef S)
Definition JSON.cpp:717
LLVM_ABI std::string fixUTF8(llvm::StringRef S)
Replaces invalid UTF-8 sequences in S with the replacement character (U+FFFD).
Definition JSON.cpp:700
static void encodeUtf8(uint32_t Rune, std::string &Out)
Definition JSON.cpp:573
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
LLVM_ABI ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, const UTF8 *sourceEnd, UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
Convert a partial UTF8 sequence to UTF32.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:98
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
@ lenientConversion
Definition ConvertUTF.h:158
@ strictConversion
Definition ConvertUTF.h:157
auto reverse(ContainerTy &&C)
Definition STLExtras.h:420
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:126
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:71
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
LLVM_ABI void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
LLVM_ABI ConversionResult ConvertUTF32toUTF8(const UTF32 **sourceStart, const UTF32 *sourceEnd, UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
bool isASCII(char C)
Checks whether character C is valid ASCII (high bit is zero).
LLVM_ABI Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd)
unsigned char UTF8
Definition ConvertUTF.h:131
unsigned int UTF32
Definition ConvertUTF.h:129