28 return try_emplace(std::move(K),
nullptr).first->getSecond();
44 return V->getAsNull();
49 return V->getAsBoolean();
54 return V->getAsNumber();
59 return V->getAsInteger();
64 return V->getAsString();
69 return V->getAsObject();
74 return V->getAsObject();
79 return V->getAsArray();
84 return V->getAsArray();
88 if (
LHS.size() !=
RHS.size())
90 for (
const auto &L :
LHS) {
91 auto R =
RHS.find(L.first);
92 if (R ==
RHS.end() || L.second != R->second)
99 V.reserve(Elements.size());
100 for (
const Value &V : Elements) {
102 back().moveFrom(std::move(V));
109void Value::copyFrom(
const Value &M) {
117 memcpy(&Union, &M.Union,
sizeof(Union));
123 create<std::string>(M.as<std::string>());
134void Value::moveFrom(
const Value &&M) {
142 memcpy(&Union, &M.Union,
sizeof(Union));
145 create<StringRef>(M.as<StringRef>());
148 create<std::string>(std::move(M.as<std::string>()));
152 create<json::Object>(std::move(M.as<json::Object>()));
156 create<json::Array>(std::move(M.as<json::Array>()));
162void Value::destroy() {
171 as<StringRef>().~StringRef();
174 as<std::string>().~basic_string();
177 as<json::Object>().~Object();
180 as<json::Array>().~Array();
186 if (L.kind() != R.kind())
190 return *L.getAsNull() == *R.getAsNull();
192 return *L.getAsBoolean() == *R.getAsBoolean();
198 if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
199 return L.getAsInteger() == R.getAsInteger();
200 return *L.getAsNumber() == *R.getAsNumber();
202 return *L.getAsString() == *R.getAsString();
204 return *L.getAsArray() == *R.getAsArray();
206 return *L.getAsObject() == *R.getAsObject();
215 for (
P =
this;
P->Parent !=
nullptr;
P =
P->Parent)
219 R->ErrorMessage = Msg;
220 R->ErrorPath.resize(Count);
221 auto It = R->ErrorPath.begin();
222 for (
P =
this;
P->Parent !=
nullptr;
P =
P->Parent)
229 OS << (ErrorMessage.
empty() ?
"invalid JSON contents" : ErrorMessage);
230 if (ErrorPath.empty()) {
232 OS <<
" when parsing " << Name;
234 OS <<
" at " << (Name.
empty() ?
"(root)" : Name);
237 OS <<
'.' << S.field();
239 OS <<
'[' << S.index() <<
']';
247std::vector<const Object::value_type *> sortedElements(
const Object &O) {
248 std::vector<const Object::value_type *> Elements;
249 for (
const auto &
E : O)
250 Elements.push_back(&
E);
253 return L->first < R->first;
261void abbreviate(
const Value &V, OStream &JOS) {
264 JOS.rawValue(V.getAsArray()->empty() ?
"[]" :
"[ ... ]");
267 JOS.rawValue(V.getAsObject()->empty() ?
"{}" :
"{ ... }");
275 Truncated.append(
"...");
276 JOS.value(Truncated);
287void abbreviateChildren(
const Value &V, OStream &JOS) {
291 for (
const auto &
I : *
V.getAsArray())
297 for (
const auto *KV : sortedElements(*
V.getAsObject())) {
298 JOS.attributeBegin(KV->first);
299 abbreviate(KV->second, JOS);
321 auto HighlightCurrent = [&] {
322 std::string Comment =
"error: ";
323 Comment.append(ErrorMessage.data(), ErrorMessage.size());
325 abbreviateChildren(V, JOS);
328 return HighlightCurrent();
329 const Segment &S =
Path.back();
333 const Object *O = V.getAsObject();
334 if (!O || !O->get(FieldName))
335 return HighlightCurrent();
337 for (
const auto *KV : sortedElements(*O)) {
340 Recurse(KV->second,
Path.drop_back(), Recurse);
342 abbreviate(KV->second, JOS);
348 const Array *
A = V.getAsArray();
349 if (!
A || S.index() >=
A->size())
350 return HighlightCurrent();
352 unsigned Current = 0;
353 for (
const auto &V : *
A) {
354 if (Current++ == S.index())
355 Recurse(V,
Path.drop_back(), Recurse);
362 PrintValue(R, ErrorPath, PrintValue);
370 : Start(JSON.begin()),
P(JSON.begin()),
End(JSON.end()) {}
376 P = Start + ErrOffset;
377 return parseError(
"Invalid UTF-8 sequence");
380 bool parseValue(
Value &Out);
386 return parseError(
"Text after end of document");
391 return std::move(*Err);
395 void eatWhitespace() {
396 while (
P !=
End && (*
P ==
' ' || *
P ==
'\r' || *
P ==
'\n' || *
P ==
'\t'))
401 bool parseNumber(
char First, Value &Out);
402 bool parseString(std::string &Out);
403 bool parseUnicode(std::string &Out);
404 bool parseError(
const char *Msg);
406 char next() {
return P ==
End ? 0 : *
P++; }
407 char peek() {
return P ==
End ? 0 : *
P; }
408 static bool isNumber(
char C) {
409 return C ==
'0' ||
C ==
'1' ||
C ==
'2' ||
C ==
'3' ||
C ==
'4' ||
410 C ==
'5' ||
C ==
'6' ||
C ==
'7' ||
C ==
'8' ||
C ==
'9' ||
411 C ==
'e' ||
C ==
'E' ||
C ==
'+' ||
C ==
'-' ||
C ==
'.';
414 std::optional<Error> Err;
415 const char *Start, *
P, *
End;
418bool Parser::parseValue(Value &Out) {
421 return parseError(
"Unexpected EOF");
422 switch (
char C = next()) {
426 return (next() ==
'u' && next() ==
'l' && next() ==
'l') ||
427 parseError(
"Invalid JSON value (null?)");
430 return (next() ==
'r' && next() ==
'u' && next() ==
'e') ||
431 parseError(
"Invalid JSON value (true?)");
434 return (next() ==
'a' && next() ==
'l' && next() ==
's' && next() ==
'e') ||
435 parseError(
"Invalid JSON value (false?)");
438 if (parseString(S)) {
446 Array &
A = *Out.getAsArray();
453 A.emplace_back(
nullptr);
454 if (!parseValue(
A.back()))
464 return parseError(
"Expected , or ] after array element");
470 Object &
O = *Out.getAsObject();
478 return parseError(
"Expected object key");
484 return parseError(
"Expected : after object key");
486 if (!parseValue(O[std::move(K)]))
496 return parseError(
"Expected , or } after object property");
502 return parseNumber(
C, Out);
503 return parseError(
"Invalid JSON value");
507bool Parser::parseNumber(
char First, Value &Out) {
511 while (isNumber(
peek()))
518 int64_t
I = std::strtoll(S.c_str(), &
End, 10);
519 if (
End == S.end() && errno != ERANGE) {
529 if (
End == S.end() && errno != ERANGE) {
535 Out = std::strtod(S.c_str(), &
End);
536 return End == S.end() || parseError(
"Invalid JSON value (number?)");
539bool Parser::parseString(std::string &Out) {
541 for (
char C = next();
C !=
'"';
C = next()) {
543 return parseError(
"Unterminated string");
545 return parseError(
"Control character in string");
551 switch (
C = next()) {
573 if (!parseUnicode(Out))
577 return parseError(
"Invalid escape sequence");
583static void encodeUtf8(
uint32_t Rune, std::string &Out) {
585 Out.push_back(Rune & 0x7F);
586 }
else if (Rune < 0x800) {
587 uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
588 uint8_t SecondByte = 0x80 | (Rune & 0x3F);
589 Out.push_back(FirstByte);
590 Out.push_back(SecondByte);
591 }
else if (Rune < 0x10000) {
592 uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
593 uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
594 uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
595 Out.push_back(FirstByte);
596 Out.push_back(SecondByte);
597 Out.push_back(ThirdByte);
598 }
else if (Rune < 0x110000) {
599 uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
600 uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
601 uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
602 uint8_t FourthByte = 0x80 | (Rune & 0x3F);
603 Out.push_back(FirstByte);
604 Out.push_back(SecondByte);
605 Out.push_back(ThirdByte);
606 Out.push_back(FourthByte);
616bool Parser::parseUnicode(std::string &Out) {
618 auto Invalid = [&] { Out.append( {
'\xef',
'\xbf',
'\xbd'}); };
620 auto Parse4Hex = [
this](
uint16_t &Out) ->
bool {
622 char Bytes[] = {next(), next(), next(), next()};
623 for (
unsigned char C : Bytes) {
624 if (!std::isxdigit(
C))
625 return parseError(
"Invalid \\u escape sequence");
627 Out |= (
C >
'9') ? (
C & ~0x20) -
'A' + 10 : (
C -
'0');
632 if (!Parse4Hex(
First))
638 if (
LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) {
639 encodeUtf8(
First, Out);
657 if (!Parse4Hex(Second))
666 encodeUtf8(0x10000 | ((
First - 0xD800) << 10) | (Second - 0xDC00), Out);
671bool Parser::parseError(
const char *Msg) {
673 const char *StartOfLine = Start;
674 for (
const char *
X = Start;
X <
P; ++
X) {
681 std::make_unique<ParseError>(Msg, Line,
P - StartOfLine,
P - Start));
693 return P.takeError();
707 *ErrOffset = Rest -
Data;
713 std::vector<UTF32> Codepoints(S.
size());
714 const UTF8 *In8 =
reinterpret_cast<const UTF8 *
>(S.
data());
715 UTF32 *Out32 = Codepoints.data();
718 Codepoints.resize(Out32 - Codepoints.data());
719 std::string Res(4 * Codepoints.size(), 0);
720 const UTF32 *In32 = Codepoints.data();
721 UTF8 *Out8 =
reinterpret_cast<UTF8 *
>(&Res[0]);
724 Res.resize(
reinterpret_cast<char *
>(Out8) - Res.data());
730 for (
unsigned char C : S) {
731 if (
C == 0x22 ||
C == 0x5C)
766 OS << (*V.getAsBoolean() ?
"true" :
"false");
770 if (V.Type == Value::T_Integer)
771 OS << *V.getAsInteger();
772 else if (V.Type == Value::T_UINT64)
773 OS << *V.getAsUINT64();
775 OS <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
784 for (
const Value &
E : *V.getAsArray())
790 attribute(
E->first,
E->second);
795void llvm::json::OStream::valueBegin() {
796 assert(Stack.back().Ctx !=
Object &&
"Only attributes allowed here");
797 if (Stack.back().HasValue) {
798 assert(Stack.back().Ctx != Singleton &&
"Only one value allowed here");
801 if (Stack.back().Ctx == Array)
804 Stack.back().HasValue =
true;
808 assert(PendingComment.empty() &&
"Only one comment per value!");
809 PendingComment = Comment;
812void OStream::flushComment() {
813 if (PendingComment.empty())
815 OS << (IndentSize ?
"/* " :
"/*");
817 while (!PendingComment.empty()) {
818 auto Pos = PendingComment.find(
"*/");
820 OS << PendingComment;
823 OS << PendingComment.take_front(Pos) <<
"* /";
824 PendingComment = PendingComment.drop_front(Pos + 2);
827 OS << (IndentSize ?
" */" :
"*/");
829 if (
Stack.size() > 1 &&
Stack.back().Ctx == Singleton) {
837void llvm::json::OStream::newline() {
846 Stack.emplace_back();
847 Stack.back().Ctx =
Array;
848 Indent += IndentSize;
854 Indent -= IndentSize;
855 if (Stack.back().HasValue)
858 assert(PendingComment.empty());
865 Stack.emplace_back();
866 Stack.back().Ctx =
Object;
867 Indent += IndentSize;
873 Indent -= IndentSize;
874 if (Stack.back().HasValue)
877 assert(PendingComment.empty());
884 if (Stack.back().HasValue)
888 Stack.back().HasValue =
true;
889 Stack.emplace_back();
890 Stack.back().Ctx = Singleton;
894 assert(
false &&
"Invalid UTF-8 in attribute key");
903 assert(Stack.back().Ctx == Singleton);
904 assert(Stack.back().HasValue &&
"Attribute must have a value");
905 assert(PendingComment.empty());
912 Stack.emplace_back();
913 Stack.back().Ctx = RawValue;
918 assert(Stack.back().Ctx == RawValue);
927 unsigned IndentAmount = 0;
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
Given that RA is a live value
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This file supports working with JSON data.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool peek(struct InternalInstruction *insn, uint8_t &byte)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Lightweight error class with error context and mandatory checking.
Tagged union holding either a T or a Error.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
static constexpr size_t npos
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
An Array is a JSON array, which contains heterogeneous JSON values.
void emplace_back(Args &&...A)
json::OStream allows writing well-formed JSON without materializing all structures as json::Value ahe...
void object(Block Contents)
Emit an object whose elements are emitted in the provided Block.
void attributeBegin(llvm::StringRef Key)
raw_ostream & rawValueBegin()
void comment(llvm::StringRef)
Emit a JavaScript comment associated with the next printed value.
void array(Block Contents)
Emit an array whose elements are emitted in the provided Block.
void value(const Value &V)
Emit a self-contained value (number, string, vector<string> etc).
ObjectKey is a used to capture keys in Object.
An Object is a JSON object, which maps strings to heterogenous JSON values.
std::optional< bool > getBoolean(StringRef K) const
Value & operator[](const ObjectKey &K)
std::optional< double > getNumber(StringRef K) const
const json::Object * getObject(StringRef K) const
std::optional< llvm::StringRef > getString(StringRef K) const
Storage::value_type value_type
std::optional< int64_t > getInteger(StringRef K) const
std::optional< std::nullptr_t > getNull(StringRef K) const
std::pair< iterator, bool > try_emplace(const ObjectKey &K, Ts &&... Args)
iterator find(StringRef K)
const json::Array * getArray(StringRef K) const
The root is the trivial Path to the root value.
void printErrorContext(const Value &, llvm::raw_ostream &) const
Print the root value with the error shown inline as a comment.
Error getError() const
Returns the last error reported, or else a generic error.
A "cursor" marking a position within a Value.
void report(llvm::StringLiteral Message)
Records that the value at the current path is invalid.
A Value is an JSON value of unknown type.
@ Number
Number values can store both int64s and doubles at full precision, depending on what they were constr...
This class implements an extremely fast bulk output stream that can only output to a stream.
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.
bool operator==(const Object &LHS, const Object &RHS)
bool isUTF8(llvm::StringRef S, size_t *ErrOffset=nullptr)
Returns true if S is valid UTF-8, which is required for use as JSON.
static void quote(llvm::raw_ostream &OS, llvm::StringRef S)
std::string fixUTF8(llvm::StringRef S)
Replaces invalid UTF-8 sequences in S with the replacement character (U+FFFD).
This is an optimization pass for GlobalISel generic memory operations.
ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, const UTF8 *sourceEnd, UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
Convert a partial UTF8 sequence to UTF32.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
ConversionResult ConvertUTF32toUTF8(const UTF32 **sourceStart, const UTF32 *sourceEnd, UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
@ Invalid
Denotes invalid value.
Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd)