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();
188 if (L.kind() != R.kind())
192 return *L.getAsNull() == *R.getAsNull();
194 return *L.getAsBoolean() == *R.getAsBoolean();
200 if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
201 return L.getAsInteger() == R.getAsInteger();
202 return *L.getAsNumber() == *R.getAsNumber();
204 return *L.getAsString() == *R.getAsString();
206 return *L.getAsArray() == *R.getAsArray();
208 return *L.getAsObject() == *R.getAsObject();
217 for (
P =
this;
P->Parent !=
nullptr;
P =
P->Parent)
221 R->ErrorMessage = Msg;
222 R->ErrorPath.resize(Count);
223 auto It = R->ErrorPath.begin();
224 for (
P =
this;
P->Parent !=
nullptr;
P =
P->Parent)
231 OS << (ErrorMessage.
empty() ?
"invalid JSON contents" : ErrorMessage);
232 if (ErrorPath.empty()) {
234 OS <<
" when parsing " << Name;
236 OS <<
" at " << (Name.
empty() ?
"(root)" : Name);
239 OS <<
'.' << S.field();
241 OS <<
'[' << S.index() <<
']';
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;
264 JOS.
rawValue(V.getAsArray()->empty() ?
"[]" :
"[ ... ]");
267 JOS.
rawValue(V.getAsObject()->empty() ?
"{}" :
"{ ... }");
275 Truncated.append(
"...");
276 JOS.
value(Truncated);
291 for (
const auto &
I : *V.getAsArray())
298 JOS.attributeBegin(KV->first);
299 abbreviate(KV->second, JOS);
319 auto HighlightCurrent = [&] {
320 std::string Comment =
"error: ";
321 Comment.append(ErrorMessage.data(), ErrorMessage.size());
326 return HighlightCurrent();
327 const Segment &S =
Path.back();
331 const Object *O = V.getAsObject();
332 if (!O || !O->get(FieldName))
333 return HighlightCurrent();
338 Recurse(KV->second,
Path.drop_back(), Recurse);
346 const Array *
A = V.getAsArray();
347 if (!
A || S.index() >=
A->size())
348 return HighlightCurrent();
350 unsigned Current = 0;
351 for (
const auto &V : *
A) {
352 if (Current++ == S.index())
353 Recurse(V,
Path.drop_back(), Recurse);
360 PrintValue(R, ErrorPath, PrintValue);
368 : Start(JSON.begin()),
P(JSON.begin()),
End(JSON.end()) {}
374 P = Start + ErrOffset;
375 return parseError(
"Invalid UTF-8 sequence");
378 bool parseValue(
Value &Out);
384 return parseError(
"Text after end of document");
389 return std::move(*Err);
393 void eatWhitespace() {
394 while (
P !=
End && (*
P ==
' ' || *
P ==
'\r' || *
P ==
'\n' || *
P ==
'\t'))
399 bool parseNumber(
char First, Value &Out);
400 bool parseString(std::string &Out);
401 bool parseUnicode(std::string &Out);
402 bool parseError(
const char *Msg);
404 char next() {
return P ==
End ? 0 : *
P++; }
405 char peek() {
return P ==
End ? 0 : *
P; }
406 static bool isNumber(
char C) {
407 return C ==
'0' ||
C ==
'1' ||
C ==
'2' ||
C ==
'3' ||
C ==
'4' ||
408 C ==
'5' ||
C ==
'6' ||
C ==
'7' ||
C ==
'8' ||
C ==
'9' ||
409 C ==
'e' ||
C ==
'E' ||
C ==
'+' ||
C ==
'-' ||
C ==
'.';
412 std::optional<Error> Err;
413 const char *Start, *
P, *
End;
417bool Parser::parseValue(Value &Out) {
420 return parseError(
"Unexpected EOF");
421 switch (
char C = next()) {
425 return (next() ==
'u' && next() ==
'l' && next() ==
'l') ||
426 parseError(
"Invalid JSON value (null?)");
429 return (next() ==
'r' && next() ==
'u' && next() ==
'e') ||
430 parseError(
"Invalid JSON value (true?)");
433 return (next() ==
'a' && next() ==
'l' && next() ==
's' && next() ==
'e') ||
434 parseError(
"Invalid JSON value (false?)");
437 if (parseString(S)) {
445 Array &
A = *Out.getAsArray();
452 A.emplace_back(
nullptr);
453 if (!parseValue(
A.back()))
463 return parseError(
"Expected , or ] after array element");
469 Object &
O = *Out.getAsObject();
477 return parseError(
"Expected object key");
483 return parseError(
"Expected : after object key");
485 if (!parseValue(O[std::move(K)]))
495 return parseError(
"Expected , or } after object property");
501 return parseNumber(
C, Out);
502 return parseError(
"Invalid JSON value");
506bool Parser::parseNumber(
char First, Value &Out) {
510 while (isNumber(
peek()))
517 int64_t
I = std::strtoll(S.c_str(), &
End, 10);
518 if (
End == S.end() && errno != ERANGE) {
528 if (
End == S.end() && errno != ERANGE) {
534 Out = std::strtod(S.c_str(), &
End);
535 return End == S.end() || parseError(
"Invalid JSON value (number?)");
538bool Parser::parseString(std::string &Out) {
540 for (
char C = next();
C !=
'"';
C = next()) {
542 return parseError(
"Unterminated string");
544 return parseError(
"Control character in string");
550 switch (
C = next()) {
572 if (!parseUnicode(Out))
576 return parseError(
"Invalid escape sequence");
584 Out.push_back(Rune & 0x7F);
585 }
else if (Rune < 0x800) {
586 uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
587 uint8_t SecondByte = 0x80 | (Rune & 0x3F);
588 Out.push_back(FirstByte);
589 Out.push_back(SecondByte);
590 }
else if (Rune < 0x10000) {
591 uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
592 uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
593 uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
594 Out.push_back(FirstByte);
595 Out.push_back(SecondByte);
596 Out.push_back(ThirdByte);
597 }
else if (Rune < 0x110000) {
598 uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
599 uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
600 uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
601 uint8_t FourthByte = 0x80 | (Rune & 0x3F);
602 Out.push_back(FirstByte);
603 Out.push_back(SecondByte);
604 Out.push_back(ThirdByte);
605 Out.push_back(FourthByte);
615bool Parser::parseUnicode(std::string &Out) {
617 auto Invalid = [&] { Out.append( {
'\xef',
'\xbf',
'\xbd'}); };
619 auto Parse4Hex = [
this](
uint16_t &Out) ->
bool {
621 char Bytes[] = {next(), next(), next(), next()};
622 for (
unsigned char C : Bytes) {
623 if (!std::isxdigit(
C))
624 return parseError(
"Invalid \\u escape sequence");
626 Out |= (
C >
'9') ? (
C & ~0x20) -
'A' + 10 : (
C -
'0');
631 if (!Parse4Hex(
First))
637 if (
LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) {
656 if (!Parse4Hex(Second))
665 encodeUtf8(0x10000 | ((
First - 0xD800) << 10) | (Second - 0xDC00), Out);
670bool Parser::parseError(
const char *Msg) {
672 const char *StartOfLine = Start;
673 for (
const char *
X = Start;
X <
P; ++
X) {
680 std::make_unique<ParseError>(Msg, Line,
P - StartOfLine,
P - Start));
691 return P.takeError();
705 *ErrOffset = Rest -
Data;
711 std::vector<UTF32> Codepoints(S.
size());
712 const UTF8 *In8 =
reinterpret_cast<const UTF8 *
>(S.
data());
713 UTF32 *Out32 = Codepoints.data();
716 Codepoints.resize(Out32 - Codepoints.data());
717 std::string Res(4 * Codepoints.size(), 0);
718 const UTF32 *In32 = Codepoints.data();
719 UTF8 *Out8 =
reinterpret_cast<UTF8 *
>(&Res[0]);
722 Res.resize(
reinterpret_cast<char *
>(Out8) - Res.data());
728 for (
unsigned char C : S) {
729 if (
C == 0x22 ||
C == 0x5C)
764 OS << (*V.getAsBoolean() ?
"true" :
"false");
768 if (V.Type == Value::T_Integer)
769 OS << *V.getAsInteger();
770 else if (V.Type == Value::T_UINT64)
771 OS << *V.getAsUINT64();
773 OS <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
782 for (
const Value &
E : *V.getAsArray())
788 attribute(
E->first,
E->second);
793void llvm::json::OStream::valueBegin() {
794 assert(Stack.back().Ctx !=
Object &&
"Only attributes allowed here");
795 if (Stack.back().HasValue) {
796 assert(Stack.back().Ctx != Singleton &&
"Only one value allowed here");
799 if (Stack.back().Ctx == Array)
802 Stack.back().HasValue =
true;
806 assert(PendingComment.empty() &&
"Only one comment per value!");
807 PendingComment = Comment;
810void OStream::flushComment() {
811 if (PendingComment.empty())
813 OS << (IndentSize ?
"/* " :
"/*");
815 while (!PendingComment.empty()) {
816 auto Pos = PendingComment.find(
"*/");
818 OS << PendingComment;
821 OS << PendingComment.take_front(Pos) <<
"* /";
822 PendingComment = PendingComment.drop_front(Pos + 2);
825 OS << (IndentSize ?
" */" :
"*/");
827 if (
Stack.size() > 1 &&
Stack.back().Ctx == Singleton) {
835void llvm::json::OStream::newline() {
844 Stack.emplace_back();
845 Stack.back().Ctx =
Array;
846 Indent += IndentSize;
852 Indent -= IndentSize;
853 if (Stack.back().HasValue)
856 assert(PendingComment.empty());
863 Stack.emplace_back();
864 Stack.back().Ctx =
Object;
865 Indent += IndentSize;
871 Indent -= IndentSize;
872 if (Stack.back().HasValue)
875 assert(PendingComment.empty());
882 if (Stack.back().HasValue)
886 Stack.back().HasValue =
true;
887 Stack.emplace_back();
888 Stack.back().Ctx = Singleton;
892 assert(
false &&
"Invalid UTF-8 in attribute key");
901 assert(Stack.back().Ctx == Singleton);
902 assert(Stack.back().HasValue &&
"Attribute must have a value");
903 assert(PendingComment.empty());
910 Stack.emplace_back();
911 Stack.back().Ctx = RawValue;
916 assert(Stack.back().Ctx == RawValue);
925 unsigned IndentAmount = 0;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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.
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.
LLVM_ABI void attributeBegin(llvm::StringRef Key)
LLVM_ABI void arrayBegin()
LLVM_ABI void objectBegin()
LLVM_ABI raw_ostream & rawValueBegin()
LLVM_ABI 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.
LLVM_ABI void attributeEnd()
LLVM_ABI void value(const Value &V)
Emit a self-contained value (number, string, vector<string> etc).
LLVM_ABI void rawValueEnd()
LLVM_ABI void objectEnd()
ObjectKey is a used to capture keys in Object.
An Object is a JSON object, which maps strings to heterogenous JSON values.
LLVM_ABI std::optional< bool > getBoolean(StringRef K) const
LLVM_ABI Value & operator[](const ObjectKey &K)
LLVM_ABI std::optional< double > getNumber(StringRef K) const
LLVM_ABI const json::Object * getObject(StringRef K) const
LLVM_ABI std::optional< llvm::StringRef > getString(StringRef K) const
Storage::value_type value_type
LLVM_ABI Value * get(StringRef K)
LLVM_ABI std::optional< int64_t > getInteger(StringRef K) const
LLVM_ABI std::optional< std::nullptr_t > getNull(StringRef K) const
std::pair< iterator, bool > try_emplace(const ObjectKey &K, Ts &&... Args)
iterator find(StringRef K)
LLVM_ABI const json::Array * getArray(StringRef K) const
The root is the trivial Path to the root value.
LLVM_ABI void printErrorContext(const Value &, llvm::raw_ostream &) const
Print the root value with the error shown inline as a comment.
LLVM_ABI Error getError() const
Returns the last error reported, or else a generic error.
A "cursor" marking a position within a Value.
LLVM_ABI void report(llvm::StringLiteral Message)
Records that the value at the current path is invalid.
A Value is an JSON value of unknown type.
LLVM_ABI void print(llvm::raw_ostream &OS) const
@ 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)
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.
LLVM_ABI std::vector< const Object::value_type * > sortedElements(const Object &O)
static void quote(llvm::raw_ostream &OS, llvm::StringRef S)
LLVM_ABI 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.
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...
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.
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)
LLVM_ABI Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd)