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() <<
']';
246 std::vector<const Object::value_type *> Elements;
247 for (
const auto &
E : O)
248 Elements.push_back(&
E);
251 return L->first < R->first;
262 JOS.
rawValue(V.getAsArray()->empty() ?
"[]" :
"[ ... ]");
265 JOS.
rawValue(V.getAsObject()->empty() ?
"{}" :
"{ ... }");
273 Truncated.append(
"...");
274 JOS.
value(Truncated);
289 for (
const auto &
I : *V.getAsArray())
296 JOS.attributeBegin(KV->first);
297 abbreviate(KV->second, JOS);
317 auto HighlightCurrent = [&] {
318 std::string Comment =
"error: ";
319 Comment.append(ErrorMessage.data(), ErrorMessage.size());
324 return HighlightCurrent();
325 const Segment &S =
Path.back();
329 const Object *O = V.getAsObject();
330 if (!O || !O->get(FieldName))
331 return HighlightCurrent();
336 Recurse(KV->second,
Path.drop_back(), Recurse);
344 const Array *
A = V.getAsArray();
345 if (!
A || S.index() >=
A->size())
346 return HighlightCurrent();
348 unsigned Current = 0;
349 for (
const auto &V : *
A) {
350 if (Current++ == S.index())
351 Recurse(V,
Path.drop_back(), Recurse);
358 PrintValue(R, ErrorPath, PrintValue);
366 : Start(JSON.begin()),
P(JSON.begin()),
End(JSON.end()) {}
372 P = Start + ErrOffset;
373 return parseError(
"Invalid UTF-8 sequence");
376 bool parseValue(
Value &Out);
382 return parseError(
"Text after end of document");
387 return std::move(*Err);
391 void eatWhitespace() {
392 while (
P !=
End && (*
P ==
' ' || *
P ==
'\r' || *
P ==
'\n' || *
P ==
'\t'))
397 bool parseNumber(
char First, Value &Out);
398 bool parseString(std::string &Out);
399 bool parseUnicode(std::string &Out);
400 bool parseError(
const char *Msg);
402 char next() {
return P ==
End ? 0 : *
P++; }
403 char peek() {
return P ==
End ? 0 : *
P; }
404 static bool isNumber(
char C) {
405 return C ==
'0' ||
C ==
'1' ||
C ==
'2' ||
C ==
'3' ||
C ==
'4' ||
406 C ==
'5' ||
C ==
'6' ||
C ==
'7' ||
C ==
'8' ||
C ==
'9' ||
407 C ==
'e' ||
C ==
'E' ||
C ==
'+' ||
C ==
'-' ||
C ==
'.';
410 std::optional<Error> Err;
411 const char *Start, *
P, *
End;
415bool Parser::parseValue(Value &Out) {
418 return parseError(
"Unexpected EOF");
419 switch (
char C = next()) {
423 return (next() ==
'u' && next() ==
'l' && next() ==
'l') ||
424 parseError(
"Invalid JSON value (null?)");
427 return (next() ==
'r' && next() ==
'u' && next() ==
'e') ||
428 parseError(
"Invalid JSON value (true?)");
431 return (next() ==
'a' && next() ==
'l' && next() ==
's' && next() ==
'e') ||
432 parseError(
"Invalid JSON value (false?)");
435 if (parseString(S)) {
443 Array &
A = *Out.getAsArray();
450 A.emplace_back(
nullptr);
451 if (!parseValue(
A.back()))
461 return parseError(
"Expected , or ] after array element");
467 Object &
O = *Out.getAsObject();
475 return parseError(
"Expected object key");
481 return parseError(
"Expected : after object key");
483 if (!parseValue(O[std::move(K)]))
493 return parseError(
"Expected , or } after object property");
499 return parseNumber(
C, Out);
500 return parseError(
"Invalid JSON value");
504bool Parser::parseNumber(
char First, Value &Out) {
508 while (isNumber(
peek()))
515 int64_t
I = std::strtoll(S.c_str(), &
End, 10);
516 if (
End == S.end() && errno != ERANGE) {
526 if (
End == S.end() && errno != ERANGE) {
532 Out = std::strtod(S.c_str(), &
End);
533 return End == S.end() || parseError(
"Invalid JSON value (number?)");
536bool Parser::parseString(std::string &Out) {
538 for (
char C = next();
C !=
'"';
C = next()) {
540 return parseError(
"Unterminated string");
542 return parseError(
"Control character in string");
548 switch (
C = next()) {
570 if (!parseUnicode(Out))
574 return parseError(
"Invalid escape sequence");
582 Out.push_back(Rune & 0x7F);
583 }
else if (Rune < 0x800) {
584 uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
585 uint8_t SecondByte = 0x80 | (Rune & 0x3F);
586 Out.push_back(FirstByte);
587 Out.push_back(SecondByte);
588 }
else if (Rune < 0x10000) {
589 uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
590 uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
591 uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
592 Out.push_back(FirstByte);
593 Out.push_back(SecondByte);
594 Out.push_back(ThirdByte);
595 }
else if (Rune < 0x110000) {
596 uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
597 uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
598 uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
599 uint8_t FourthByte = 0x80 | (Rune & 0x3F);
600 Out.push_back(FirstByte);
601 Out.push_back(SecondByte);
602 Out.push_back(ThirdByte);
603 Out.push_back(FourthByte);
613bool Parser::parseUnicode(std::string &Out) {
615 auto Invalid = [&] { Out.append( {
'\xef',
'\xbf',
'\xbd'}); };
617 auto Parse4Hex = [
this](
uint16_t &Out) ->
bool {
619 char Bytes[] = {next(), next(), next(), next()};
620 for (
unsigned char C : Bytes) {
621 if (!std::isxdigit(
C))
622 return parseError(
"Invalid \\u escape sequence");
624 Out |= (
C >
'9') ? (
C & ~0x20) -
'A' + 10 : (
C -
'0');
629 if (!Parse4Hex(
First))
635 if (
LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) {
654 if (!Parse4Hex(Second))
663 encodeUtf8(0x10000 | ((
First - 0xD800) << 10) | (Second - 0xDC00), Out);
668bool Parser::parseError(
const char *Msg) {
670 const char *StartOfLine = Start;
671 for (
const char *
X = Start;
X <
P; ++
X) {
678 std::make_unique<ParseError>(Msg, Line,
P - StartOfLine,
P - Start));
689 return P.takeError();
703 *ErrOffset = Rest -
Data;
709 std::vector<UTF32> Codepoints(S.
size());
710 const UTF8 *In8 =
reinterpret_cast<const UTF8 *
>(S.
data());
711 UTF32 *Out32 = Codepoints.data();
714 Codepoints.resize(Out32 - Codepoints.data());
715 std::string Res(4 * Codepoints.size(), 0);
716 const UTF32 *In32 = Codepoints.data();
717 UTF8 *Out8 =
reinterpret_cast<UTF8 *
>(&Res[0]);
720 Res.resize(
reinterpret_cast<char *
>(Out8) - Res.data());
726 for (
unsigned char C : S) {
727 if (
C == 0x22 ||
C == 0x5C)
762 OS << (*V.getAsBoolean() ?
"true" :
"false");
766 if (V.Type == Value::T_Integer)
767 OS << *V.getAsInteger();
768 else if (V.Type == Value::T_UINT64)
769 OS << *V.getAsUINT64();
771 OS <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
780 for (
const Value &
E : *V.getAsArray())
786 attribute(
E->first,
E->second);
791void llvm::json::OStream::valueBegin() {
792 assert(Stack.back().Ctx !=
Object &&
"Only attributes allowed here");
793 if (Stack.back().HasValue) {
794 assert(Stack.back().Ctx != Singleton &&
"Only one value allowed here");
797 if (Stack.back().Ctx == Array)
800 Stack.back().HasValue =
true;
804 assert(PendingComment.empty() &&
"Only one comment per value!");
805 PendingComment = Comment;
808void OStream::flushComment() {
809 if (PendingComment.empty())
811 OS << (IndentSize ?
"/* " :
"/*");
813 while (!PendingComment.empty()) {
814 auto Pos = PendingComment.find(
"*/");
816 OS << PendingComment;
819 OS << PendingComment.take_front(Pos) <<
"* /";
820 PendingComment = PendingComment.drop_front(Pos + 2);
823 OS << (IndentSize ?
" */" :
"*/");
825 if (
Stack.size() > 1 &&
Stack.back().Ctx == Singleton) {
833void llvm::json::OStream::newline() {
842 Stack.emplace_back();
843 Stack.back().Ctx =
Array;
844 Indent += IndentSize;
850 Indent -= IndentSize;
851 if (Stack.back().HasValue)
854 assert(PendingComment.empty());
861 Stack.emplace_back();
862 Stack.back().Ctx =
Object;
863 Indent += IndentSize;
869 Indent -= IndentSize;
870 if (Stack.back().HasValue)
873 assert(PendingComment.empty());
880 if (Stack.back().HasValue)
884 Stack.back().HasValue =
true;
885 Stack.emplace_back();
886 Stack.back().Ctx = Singleton;
890 assert(
false &&
"Invalid UTF-8 in attribute key");
899 assert(Stack.back().Ctx == Singleton);
900 assert(Stack.back().HasValue &&
"Attribute must have a value");
901 assert(PendingComment.empty());
908 Stack.emplace_back();
909 Stack.back().Ctx = RawValue;
914 assert(Stack.back().Ctx == RawValue);
923 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.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
static constexpr size_t npos
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 rawValue(llvm::function_ref< void(raw_ostream &)> Contents)
Emit an externally-serialized value.
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.
static void abbreviateChildren(const Value &V, OStream &JOS)
static void abbreviate(const Value &V, OStream &JOS)
bool isUTF8(llvm::StringRef S, size_t *ErrOffset=nullptr)
Returns true if S is valid UTF-8, which is required for use as JSON.
std::vector< const Object::value_type * > sortedElements(const Object &O)
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).
static void encodeUtf8(uint32_t Rune, std::string &Out)
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.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
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)
Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd)