22 return try_emplace(std::move(K),
nullptr).first->getSecond();
38 return V->getAsNull();
43 return V->getAsBoolean();
48 return V->getAsNumber();
53 return V->getAsInteger();
58 return V->getAsString();
63 return V->getAsObject();
68 return V->getAsObject();
73 return V->getAsArray();
78 return V->getAsArray();
84 for (
const auto &L : LHS) {
85 auto R = RHS.
find(L.first);
86 if (R == RHS.
end() || L.second != R->second)
93 V.reserve(Elements.size());
94 for (
const Value &V : Elements) {
95 emplace_back(
nullptr);
96 back().moveFrom(std::move(V));
103 void Value::copyFrom(
const Value &M) {
110 memcpy(Union.buffer, M.Union.buffer,
sizeof(Union.buffer));
116 create<std::string>(M.as<std::string>());
127 void Value::moveFrom(
const Value &&M) {
134 memcpy(Union.buffer, M.Union.buffer,
sizeof(Union.buffer));
140 create<std::string>(std::move(M.as<std::string>()));
148 create<json::Array>(std::move(M.as<
json::Array>()));
154 void Value::destroy() {
165 as<std::string>().~basic_string();
168 as<json::Object>().~
Object();
171 as<json::Array>().~
Array();
189 if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
213 P = Start + ErrOffset;
214 return parseError(
"Invalid UTF-8 sequence");
217 bool parseValue(
Value &Out);
223 return parseError(
"Text after end of document");
228 return std::move(*Err);
232 void eatWhitespace() {
233 while (
P != End && (*
P ==
' ' || *
P ==
'\r' || *
P ==
'\n' || *
P ==
'\t'))
238 bool parseNumber(
char First,
Value &Out);
239 bool parseString(std::string &Out);
240 bool parseUnicode(std::string &Out);
241 bool parseError(
const char *Msg);
243 char next() {
return P == End ? 0 : *
P++; }
244 char peek() {
return P == End ? 0 : *
P; }
245 static bool isNumber(
char C) {
246 return C ==
'0' || C ==
'1' || C ==
'2' || C ==
'3' || C ==
'4' ||
247 C ==
'5' || C ==
'6' || C ==
'7' || C ==
'8' || C ==
'9' ||
248 C ==
'e' || C ==
'E' || C ==
'+' || C ==
'-' || C ==
'.';
252 const char *Start, *
P, *End;
255 bool Parser::parseValue(
Value &Out) {
258 return parseError(
"Unexpected EOF");
259 switch (
char C = next()) {
263 return (next() ==
'u' && next() ==
'l' && next() ==
'l') ||
264 parseError(
"Invalid JSON value (null?)");
267 return (next() ==
'r' && next() ==
'u' && next() ==
'e') ||
268 parseError(
"Invalid JSON value (true?)");
271 return (next() ==
'a' && next() ==
'l' && next() ==
's' && next() ==
'e') ||
272 parseError(
"Invalid JSON value (false?)");
275 if (parseString(S)) {
291 if (!parseValue(A.
back()))
301 return parseError(
"Expected , or ] after array element");
315 return parseError(
"Expected object key");
321 return parseError(
"Expected : after object key");
323 if (!parseValue(O[std::move(K)]))
333 return parseError(
"Expected , or } after object property");
339 return parseNumber(
C, Out);
340 return parseError(
"Invalid JSON value");
344 bool Parser::parseNumber(
char First,
Value &Out) {
348 while (isNumber(peek()))
353 auto I = std::strtoll(S.
c_str(), &End, 10);
354 if (End == S.
end() &&
I >= std::numeric_limits<int64_t>::min() &&
360 Out = std::strtod(S.
c_str(), &End);
361 return End == S.
end() || parseError(
"Invalid JSON value (number?)");
364 bool Parser::parseString(std::string &Out) {
366 for (
char C = next();
C !=
'"';
C = next()) {
368 return parseError(
"Unterminated string");
370 return parseError(
"Control character in string");
376 switch (
C = next()) {
398 if (!parseUnicode(Out))
402 return parseError(
"Invalid escape sequence");
408 static void encodeUtf8(
uint32_t Rune, std::string &Out) {
410 Out.push_back(Rune & 0x7F);
411 }
else if (Rune < 0x800) {
412 uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
413 uint8_t SecondByte = 0x80 | (Rune & 0x3F);
414 Out.push_back(FirstByte);
415 Out.push_back(SecondByte);
416 }
else if (Rune < 0x10000) {
417 uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
418 uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
419 uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
420 Out.push_back(FirstByte);
421 Out.push_back(SecondByte);
422 Out.push_back(ThirdByte);
423 }
else if (Rune < 0x110000) {
424 uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
425 uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
426 uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
427 uint8_t FourthByte = 0x80 | (Rune & 0x3F);
428 Out.push_back(FirstByte);
429 Out.push_back(SecondByte);
430 Out.push_back(ThirdByte);
431 Out.push_back(FourthByte);
441 bool Parser::parseUnicode(std::string &Out) {
443 auto Invalid = [&] { Out.append( {
'\xef',
'\xbf',
'\xbd'}); };
445 auto Parse4Hex = [
this](uint16_t &Out) ->
bool {
447 char Bytes[] = {next(), next(), next(), next()};
448 for (
unsigned char C : Bytes) {
449 if (!std::isxdigit(
C))
450 return parseError(
"Invalid \\u escape sequence");
452 Out |= (
C >
'9') ? (
C & ~0x20) -
'A' + 10 : (
C -
'0');
457 if (!Parse4Hex(First))
463 if (
LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) {
464 encodeUtf8(First, Out);
482 if (!Parse4Hex(Second))
491 encodeUtf8(0x10000 | ((First - 0xD800) << 10) | (Second - 0xDC00), Out);
496 bool Parser::parseError(
const char *Msg) {
498 const char *StartOfLine = Start;
499 for (
const char *
X = Start;
X <
P; ++
X) {
506 llvm::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start));
518 return P.takeError();
523 std::vector<const Object::value_type *> Elements;
524 for (
const auto &
E : O)
525 Elements.push_back(&
E);
528 return L->first < R->first;
543 *ErrOffset = Rest - Data;
549 std::vector<UTF32> Codepoints(S.
size());
550 const UTF8 *In8 =
reinterpret_cast<const UTF8 *
>(S.
data());
551 UTF32 *Out32 = Codepoints.data();
554 Codepoints.resize(Out32 - Codepoints.data());
555 std::string Res(4 * Codepoints.size(), 0);
556 const UTF32 *In32 = Codepoints.data();
557 UTF8 *Out8 =
reinterpret_cast<UTF8 *
>(&Res[0]);
560 Res.resize(reinterpret_cast<char *>(Out8) - Res.data());
569 for (
unsigned char C : S) {
570 if (
C == 0x22 ||
C == 0x5C)
605 template <
typename Indenter>
606 void llvm::json::Value::print(raw_ostream &OS,
const Indenter &
I)
const {
612 OS << (as<bool>() ?
"true" :
"false");
615 OS <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
622 quote(OS, as<StringRef>());
625 quote(OS, as<std::string>());
639 P->second.print(OS, I);
651 for (
const auto &
E : as<json::Array>()) {
669 if (Options.
empty()) {
673 unsigned IndentAmount = 0;
676 unsigned IndentLevel = 0;
687 IndentLevel += IndentAmount;
690 IndentLevel -= IndentAmount;
An Object is a JSON object, which maps strings to heterogenous JSON values.
llvm::Optional< std::nullptr_t > getAsNull() const
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const json::Array * getAsArray() const
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
friend bool operator==(const Value &, const Value &)
void push_back(const T &Elt)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
const json::Array * getArray(StringRef K) const
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
An Array is a JSON array, which contains heterogeneous JSON values.
bool isASCII(char C)
Checks whether character C is valid ASCII (high bit is zero).
llvm::Optional< bool > getAsBoolean() const
bool isUTF8(llvm::StringRef S, size_t *ErrOffset=nullptr)
Returns true if S is valid UTF-8, which is required for use as JSON.
ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, const UTF8 *sourceEnd, UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
Convert a partial UTF8 sequence to UTF32.
std::pair< iterator, bool > try_emplace(const ObjectKey &K, Ts &&... Args)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
#define LLVM_UNLIKELY(EXPR)
const json::Object * getAsObject() const
llvm::Optional< int64_t > getAsInteger() const
llvm::Optional< double > getNumber(StringRef K) const
Tagged union holding either a T or a Error.
llvm::Optional< llvm::StringRef > getString(StringRef K) const
llvm::Optional< std::nullptr_t > getNull(StringRef K) const
static std::vector< const Object::value_type * > sortedElements(const Object &O)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
void emplace_back(Args &&... A)
ObjectKey is a used to capture keys in Object.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
bool operator==(const Object &LHS, const Object &RHS)
const json::Object * getObject(StringRef K) const
ConversionResult ConvertUTF32toUTF8(const UTF32 **sourceStart, const UTF32 *sourceEnd, UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
The instances of the Type class are immutable: once they are created, they are never changed...
A Value is an JSON value of unknown type.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd)
Number values can store both int64s and doubles at full precision, depending on what they were constr...
llvm::Expected< Value > parse(llvm::StringRef JSON)
Parses the provided JSON source, or returns a ParseError.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void sort(IteratorTy Start, IteratorTy End)
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
llvm::Optional< llvm::StringRef > getAsString() const
std::string fixUTF8(llvm::StringRef S)
Replaces invalid UTF-8 sequences in S with the replacement character (U+FFFD).
llvm::Optional< int64_t > getInteger(StringRef K) const
llvm::Optional< double > getAsNumber() const
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, Optional< size_t > Width=None)
iterator find(StringRef K)
Value & operator[](const ObjectKey &K)
static void quote(llvm::raw_ostream &OS, llvm::StringRef S)
This file supports working with JSON data.
llvm::Optional< bool > getBoolean(StringRef K) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
This class implements an extremely fast bulk output stream that can only output to a stream...
#define LLVM_LIKELY(EXPR)
StringRef - Represent a constant reference to a string, i.e.
llvm::raw_ostream & operator<<(llvm::raw_ostream &, const Value &)