003 File Manager
Current Path:
/usr/src/contrib/llvm-project/llvm/lib/Support
usr
/
src
/
contrib
/
llvm-project
/
llvm
/
lib
/
Support
/
๐
..
๐
AArch64TargetParser.cpp
(8 KB)
๐
ABIBreak.cpp
(811 B)
๐
AMDGPUMetadata.cpp
(9.37 KB)
๐
APFloat.cpp
(155.26 KB)
๐
APInt.cpp
(98.08 KB)
๐
APSInt.cpp
(1.44 KB)
๐
ARMAttributeParser.cpp
(13.94 KB)
๐
ARMBuildAttrs.cpp
(3.45 KB)
๐
ARMTargetParser.cpp
(18.09 KB)
๐
ARMWinEH.cpp
(1.08 KB)
๐
Allocator.cpp
(1.35 KB)
๐
Atomic.cpp
(1.6 KB)
๐
BinaryStreamError.cpp
(1.76 KB)
๐
BinaryStreamReader.cpp
(5.24 KB)
๐
BinaryStreamRef.cpp
(4.76 KB)
๐
BinaryStreamWriter.cpp
(3.36 KB)
๐
BlockFrequency.cpp
(2.12 KB)
๐
BranchProbability.cpp
(3.44 KB)
๐
BuryPointer.cpp
(1.11 KB)
๐
COM.cpp
(737 B)
๐
COPYRIGHT.regex
(2.65 KB)
๐
CRC.cpp
(5.23 KB)
๐
CachePruning.cpp
(10.33 KB)
๐
Chrono.cpp
(3.17 KB)
๐
CodeGenCoverage.cpp
(3.61 KB)
๐
CommandLine.cpp
(89.06 KB)
๐
Compression.cpp
(3.84 KB)
๐
ConvertUTF.cpp
(27.27 KB)
๐
ConvertUTFWrapper.cpp
(8.66 KB)
๐
CrashRecoveryContext.cpp
(15.45 KB)
๐
DAGDeltaAlgorithm.cpp
(12.47 KB)
๐
DJB.cpp
(2.71 KB)
๐
DataExtractor.cpp
(7.25 KB)
๐
Debug.cpp
(5.64 KB)
๐
DebugCounter.cpp
(4.95 KB)
๐
DeltaAlgorithm.cpp
(3.41 KB)
๐
DynamicLibrary.cpp
(6.25 KB)
๐
ELFAttributeParser.cpp
(7.27 KB)
๐
ELFAttributes.cpp
(1.27 KB)
๐
Errno.cpp
(2.18 KB)
๐
Error.cpp
(4.72 KB)
๐
ErrorHandling.cpp
(11.08 KB)
๐
ExtensibleRTTI.cpp
(446 B)
๐
FileCheck.cpp
(95.77 KB)
๐
FileCheckImpl.h
(34.14 KB)
๐
FileCollector.cpp
(9.01 KB)
๐
FileOutputBuffer.cpp
(6.62 KB)
๐
FileUtilities.cpp
(10.81 KB)
๐
FoldingSet.cpp
(15.89 KB)
๐
FormatVariadic.cpp
(5.17 KB)
๐
FormattedStream.cpp
(5.29 KB)
๐
GlobPattern.cpp
(5 KB)
๐
GraphWriter.cpp
(9.21 KB)
๐
Hashing.cpp
(1.16 KB)
๐
Host.cpp
(51.63 KB)
๐
InitLLVM.cpp
(1.92 KB)
๐
IntEqClasses.cpp
(2.18 KB)
๐
IntervalMap.cpp
(4.4 KB)
๐
ItaniumManglingCanonicalizer.cpp
(10.77 KB)
๐
JSON.cpp
(19.1 KB)
๐
KnownBits.cpp
(3.78 KB)
๐
LEB128.cpp
(1.19 KB)
๐
LineIterator.cpp
(2.61 KB)
๐
Locale.cpp
(377 B)
๐
LockFileManager.cpp
(10.64 KB)
๐
LowLevelType.cpp
(2.09 KB)
๐
MD5.cpp
(8.99 KB)
๐
ManagedStatic.cpp
(2.37 KB)
๐
MathExtras.cpp
(913 B)
๐
MemAlloc.cpp
(1.01 KB)
๐
Memory.cpp
(1.57 KB)
๐
MemoryBuffer.cpp
(18.99 KB)
๐
NativeFormatting.cpp
(7.54 KB)
๐
OptimizedStructLayout.cpp
(16.7 KB)
๐
Optional.cpp
(530 B)
๐
Parallel.cpp
(5.08 KB)
๐
Path.cpp
(36.52 KB)
๐
PluginLoader.cpp
(1.63 KB)
๐
PrettyStackTrace.cpp
(10.33 KB)
๐
Process.cpp
(3.27 KB)
๐
Program.cpp
(3.54 KB)
๐
RISCVAttributeParser.cpp
(2.06 KB)
๐
RISCVAttributes.cpp
(970 B)
๐
RWMutex.cpp
(3.23 KB)
๐
RandomNumberGenerator.cpp
(2.86 KB)
๐
Regex.cpp
(6.38 KB)
๐
SHA1.cpp
(10.43 KB)
๐
ScaledNumber.cpp
(9.09 KB)
๐
ScopedPrinter.cpp
(1.19 KB)
๐
Signals.cpp
(8.35 KB)
๐
Signposts.cpp
(3.24 KB)
๐
SmallPtrSet.cpp
(9.21 KB)
๐
SmallVector.cpp
(3.99 KB)
๐
SourceMgr.cpp
(20.08 KB)
๐
SpecialCaseList.cpp
(7.48 KB)
๐
Statistic.cpp
(8.85 KB)
๐
StringExtras.cpp
(4.34 KB)
๐
StringMap.cpp
(9.31 KB)
๐
StringRef.cpp
(17.41 KB)
๐
StringSaver.cpp
(882 B)
๐
SuffixTree.cpp
(7.23 KB)
๐
SymbolRemappingReader.cpp
(2.94 KB)
๐
SystemUtils.cpp
(1.06 KB)
๐
TarWriter.cpp
(7.23 KB)
๐
TargetParser.cpp
(9.86 KB)
๐
TargetRegistry.cpp
(4.6 KB)
๐
ThreadLocal.cpp
(1.68 KB)
๐
ThreadPool.cpp
(4.4 KB)
๐
Threading.cpp
(4.55 KB)
๐
TimeProfiler.cpp
(11.63 KB)
๐
Timer.cpp
(14.14 KB)
๐
ToolOutputFile.cpp
(1.83 KB)
๐
TrigramIndex.cpp
(3.24 KB)
๐
Triple.cpp
(53.17 KB)
๐
Twine.cpp
(4.6 KB)
๐
Unicode.cpp
(20.14 KB)
๐
UnicodeCaseFold.cpp
(15.32 KB)
๐
Unix
๐
Valgrind.cpp
(1.6 KB)
๐
VersionTuple.cpp
(2.74 KB)
๐
VirtualFileSystem.cpp
(74.17 KB)
๐
Watchdog.cpp
(738 B)
๐
Windows
๐
WithColor.cpp
(4.35 KB)
๐
X86TargetParser.cpp
(27.21 KB)
๐
YAMLParser.cpp
(68.53 KB)
๐
YAMLTraits.cpp
(28.37 KB)
๐
Z3Solver.cpp
(31.44 KB)
๐
circular_raw_ostream.cpp
(1.3 KB)
๐
raw_os_ostream.cpp
(995 B)
๐
raw_ostream.cpp
(28.97 KB)
๐
regcomp.c
(39.42 KB)
๐
regengine.inc
(26.49 KB)
๐
regerror.c
(4.42 KB)
๐
regex2.h
(6.82 KB)
๐
regex_impl.h
(3.63 KB)
๐
regexec.c
(5.71 KB)
๐
regfree.c
(2.49 KB)
๐
regstrlcpy.c
(1.56 KB)
๐
regutils.h
(2.25 KB)
๐
xxhash.cpp
(4.07 KB)
Editing: JSON.cpp
//=== JSON.cpp - JSON value, parsing and serialization - C++ -----------*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===---------------------------------------------------------------------===// #include "llvm/Support/JSON.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Format.h" #include <cctype> namespace llvm { namespace json { Value &Object::operator[](const ObjectKey &K) { return try_emplace(K, nullptr).first->getSecond(); } Value &Object::operator[](ObjectKey &&K) { return try_emplace(std::move(K), nullptr).first->getSecond(); } Value *Object::get(StringRef K) { auto I = find(K); if (I == end()) return nullptr; return &I->second; } const Value *Object::get(StringRef K) const { auto I = find(K); if (I == end()) return nullptr; return &I->second; } llvm::Optional<std::nullptr_t> Object::getNull(StringRef K) const { if (auto *V = get(K)) return V->getAsNull(); return llvm::None; } llvm::Optional<bool> Object::getBoolean(StringRef K) const { if (auto *V = get(K)) return V->getAsBoolean(); return llvm::None; } llvm::Optional<double> Object::getNumber(StringRef K) const { if (auto *V = get(K)) return V->getAsNumber(); return llvm::None; } llvm::Optional<int64_t> Object::getInteger(StringRef K) const { if (auto *V = get(K)) return V->getAsInteger(); return llvm::None; } llvm::Optional<llvm::StringRef> Object::getString(StringRef K) const { if (auto *V = get(K)) return V->getAsString(); return llvm::None; } const json::Object *Object::getObject(StringRef K) const { if (auto *V = get(K)) return V->getAsObject(); return nullptr; } json::Object *Object::getObject(StringRef K) { if (auto *V = get(K)) return V->getAsObject(); return nullptr; } const json::Array *Object::getArray(StringRef K) const { if (auto *V = get(K)) return V->getAsArray(); return nullptr; } json::Array *Object::getArray(StringRef K) { if (auto *V = get(K)) return V->getAsArray(); return nullptr; } bool operator==(const Object &LHS, const Object &RHS) { if (LHS.size() != RHS.size()) return false; for (const auto &L : LHS) { auto R = RHS.find(L.first); if (R == RHS.end() || L.second != R->second) return false; } return true; } Array::Array(std::initializer_list<Value> Elements) { V.reserve(Elements.size()); for (const Value &V : Elements) { emplace_back(nullptr); back().moveFrom(std::move(V)); } } Value::Value(std::initializer_list<Value> Elements) : Value(json::Array(Elements)) {} void Value::copyFrom(const Value &M) { Type = M.Type; switch (Type) { case T_Null: case T_Boolean: case T_Double: case T_Integer: memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer)); break; case T_StringRef: create<StringRef>(M.as<StringRef>()); break; case T_String: create<std::string>(M.as<std::string>()); break; case T_Object: create<json::Object>(M.as<json::Object>()); break; case T_Array: create<json::Array>(M.as<json::Array>()); break; } } void Value::moveFrom(const Value &&M) { Type = M.Type; switch (Type) { case T_Null: case T_Boolean: case T_Double: case T_Integer: memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer)); break; case T_StringRef: create<StringRef>(M.as<StringRef>()); break; case T_String: create<std::string>(std::move(M.as<std::string>())); M.Type = T_Null; break; case T_Object: create<json::Object>(std::move(M.as<json::Object>())); M.Type = T_Null; break; case T_Array: create<json::Array>(std::move(M.as<json::Array>())); M.Type = T_Null; break; } } void Value::destroy() { switch (Type) { case T_Null: case T_Boolean: case T_Double: case T_Integer: break; case T_StringRef: as<StringRef>().~StringRef(); break; case T_String: as<std::string>().~basic_string(); break; case T_Object: as<json::Object>().~Object(); break; case T_Array: as<json::Array>().~Array(); break; } } bool operator==(const Value &L, const Value &R) { if (L.kind() != R.kind()) return false; switch (L.kind()) { case Value::Null: return *L.getAsNull() == *R.getAsNull(); case Value::Boolean: return *L.getAsBoolean() == *R.getAsBoolean(); case Value::Number: // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 // The same integer must convert to the same double, per the standard. // However we see 64-vs-80-bit precision comparisons with gcc-7 -O3 -m32. // So we avoid floating point promotion for exact comparisons. if (L.Type == Value::T_Integer || R.Type == Value::T_Integer) return L.getAsInteger() == R.getAsInteger(); return *L.getAsNumber() == *R.getAsNumber(); case Value::String: return *L.getAsString() == *R.getAsString(); case Value::Array: return *L.getAsArray() == *R.getAsArray(); case Value::Object: return *L.getAsObject() == *R.getAsObject(); } llvm_unreachable("Unknown value kind"); } namespace { // Simple recursive-descent JSON parser. class Parser { public: Parser(StringRef JSON) : Start(JSON.begin()), P(JSON.begin()), End(JSON.end()) {} bool checkUTF8() { size_t ErrOffset; if (isUTF8(StringRef(Start, End - Start), &ErrOffset)) return true; P = Start + ErrOffset; // For line/column calculation. return parseError("Invalid UTF-8 sequence"); } bool parseValue(Value &Out); bool assertEnd() { eatWhitespace(); if (P == End) return true; return parseError("Text after end of document"); } Error takeError() { assert(Err); return std::move(*Err); } private: void eatWhitespace() { while (P != End && (*P == ' ' || *P == '\r' || *P == '\n' || *P == '\t')) ++P; } // On invalid syntax, parseX() functions return false and set Err. bool parseNumber(char First, Value &Out); bool parseString(std::string &Out); bool parseUnicode(std::string &Out); bool parseError(const char *Msg); // always returns false char next() { return P == End ? 0 : *P++; } char peek() { return P == End ? 0 : *P; } static bool isNumber(char C) { return C == '0' || C == '1' || C == '2' || C == '3' || C == '4' || C == '5' || C == '6' || C == '7' || C == '8' || C == '9' || C == 'e' || C == 'E' || C == '+' || C == '-' || C == '.'; } Optional<Error> Err; const char *Start, *P, *End; }; bool Parser::parseValue(Value &Out) { eatWhitespace(); if (P == End) return parseError("Unexpected EOF"); switch (char C = next()) { // Bare null/true/false are easy - first char identifies them. case 'n': Out = nullptr; return (next() == 'u' && next() == 'l' && next() == 'l') || parseError("Invalid JSON value (null?)"); case 't': Out = true; return (next() == 'r' && next() == 'u' && next() == 'e') || parseError("Invalid JSON value (true?)"); case 'f': Out = false; return (next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') || parseError("Invalid JSON value (false?)"); case '"': { std::string S; if (parseString(S)) { Out = std::move(S); return true; } return false; } case '[': { Out = Array{}; Array &A = *Out.getAsArray(); eatWhitespace(); if (peek() == ']') { ++P; return true; } for (;;) { A.emplace_back(nullptr); if (!parseValue(A.back())) return false; eatWhitespace(); switch (next()) { case ',': eatWhitespace(); continue; case ']': return true; default: return parseError("Expected , or ] after array element"); } } } case '{': { Out = Object{}; Object &O = *Out.getAsObject(); eatWhitespace(); if (peek() == '}') { ++P; return true; } for (;;) { if (next() != '"') return parseError("Expected object key"); std::string K; if (!parseString(K)) return false; eatWhitespace(); if (next() != ':') return parseError("Expected : after object key"); eatWhitespace(); if (!parseValue(O[std::move(K)])) return false; eatWhitespace(); switch (next()) { case ',': eatWhitespace(); continue; case '}': return true; default: return parseError("Expected , or } after object property"); } } } default: if (isNumber(C)) return parseNumber(C, Out); return parseError("Invalid JSON value"); } } bool Parser::parseNumber(char First, Value &Out) { // Read the number into a string. (Must be null-terminated for strto*). SmallString<24> S; S.push_back(First); while (isNumber(peek())) S.push_back(next()); char *End; // Try first to parse as integer, and if so preserve full 64 bits. // strtoll returns long long >= 64 bits, so check it's in range too. auto I = std::strtoll(S.c_str(), &End, 10); if (End == S.end() && I >= std::numeric_limits<int64_t>::min() && I <= std::numeric_limits<int64_t>::max()) { Out = int64_t(I); return true; } // If it's not an integer Out = std::strtod(S.c_str(), &End); return End == S.end() || parseError("Invalid JSON value (number?)"); } bool Parser::parseString(std::string &Out) { // leading quote was already consumed. for (char C = next(); C != '"'; C = next()) { if (LLVM_UNLIKELY(P == End)) return parseError("Unterminated string"); if (LLVM_UNLIKELY((C & 0x1f) == C)) return parseError("Control character in string"); if (LLVM_LIKELY(C != '\\')) { Out.push_back(C); continue; } // Handle escape sequence. switch (C = next()) { case '"': case '\\': case '/': Out.push_back(C); break; case 'b': Out.push_back('\b'); break; case 'f': Out.push_back('\f'); break; case 'n': Out.push_back('\n'); break; case 'r': Out.push_back('\r'); break; case 't': Out.push_back('\t'); break; case 'u': if (!parseUnicode(Out)) return false; break; default: return parseError("Invalid escape sequence"); } } return true; } static void encodeUtf8(uint32_t Rune, std::string &Out) { if (Rune < 0x80) { Out.push_back(Rune & 0x7F); } else if (Rune < 0x800) { uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6); uint8_t SecondByte = 0x80 | (Rune & 0x3F); Out.push_back(FirstByte); Out.push_back(SecondByte); } else if (Rune < 0x10000) { uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12); uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6); uint8_t ThirdByte = 0x80 | (Rune & 0x3F); Out.push_back(FirstByte); Out.push_back(SecondByte); Out.push_back(ThirdByte); } else if (Rune < 0x110000) { uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18); uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12); uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6); uint8_t FourthByte = 0x80 | (Rune & 0x3F); Out.push_back(FirstByte); Out.push_back(SecondByte); Out.push_back(ThirdByte); Out.push_back(FourthByte); } else { llvm_unreachable("Invalid codepoint"); } } // Parse a UTF-16 \uNNNN escape sequence. "\u" has already been consumed. // May parse several sequential escapes to ensure proper surrogate handling. // We do not use ConvertUTF.h, it can't accept and replace unpaired surrogates. // These are invalid Unicode but valid JSON (RFC 8259, section 8.2). bool Parser::parseUnicode(std::string &Out) { // Invalid UTF is not a JSON error (RFC 8529ยง8.2). It gets replaced by U+FFFD. auto Invalid = [&] { Out.append(/* UTF-8 */ {'\xef', '\xbf', '\xbd'}); }; // Decodes 4 hex digits from the stream into Out, returns false on error. auto Parse4Hex = [this](uint16_t &Out) -> bool { Out = 0; char Bytes[] = {next(), next(), next(), next()}; for (unsigned char C : Bytes) { if (!std::isxdigit(C)) return parseError("Invalid \\u escape sequence"); Out <<= 4; Out |= (C > '9') ? (C & ~0x20) - 'A' + 10 : (C - '0'); } return true; }; uint16_t First; // UTF-16 code unit from the first \u escape. if (!Parse4Hex(First)) return false; // We loop to allow proper surrogate-pair error handling. while (true) { // Case 1: the UTF-16 code unit is already a codepoint in the BMP. if (LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) { encodeUtf8(First, Out); return true; } // Case 2: it's an (unpaired) trailing surrogate. if (LLVM_UNLIKELY(First >= 0xDC00)) { Invalid(); return true; } // Case 3: it's a leading surrogate. We expect a trailing one next. // Case 3a: there's no trailing \u escape. Don't advance in the stream. if (LLVM_UNLIKELY(P + 2 > End || *P != '\\' || *(P + 1) != 'u')) { Invalid(); // Leading surrogate was unpaired. return true; } P += 2; uint16_t Second; if (!Parse4Hex(Second)) return false; // Case 3b: there was another \u escape, but it wasn't a trailing surrogate. if (LLVM_UNLIKELY(Second < 0xDC00 || Second >= 0xE000)) { Invalid(); // Leading surrogate was unpaired. First = Second; // Second escape still needs to be processed. continue; } // Case 3c: a valid surrogate pair encoding an astral codepoint. encodeUtf8(0x10000 | ((First - 0xD800) << 10) | (Second - 0xDC00), Out); return true; } } bool Parser::parseError(const char *Msg) { int Line = 1; const char *StartOfLine = Start; for (const char *X = Start; X < P; ++X) { if (*X == 0x0A) { ++Line; StartOfLine = X + 1; } } Err.emplace( std::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start)); return false; } } // namespace Expected<Value> parse(StringRef JSON) { Parser P(JSON); Value E = nullptr; if (P.checkUTF8()) if (P.parseValue(E)) if (P.assertEnd()) return std::move(E); return P.takeError(); } char ParseError::ID = 0; static std::vector<const Object::value_type *> sortedElements(const Object &O) { std::vector<const Object::value_type *> Elements; for (const auto &E : O) Elements.push_back(&E); llvm::sort(Elements, [](const Object::value_type *L, const Object::value_type *R) { return L->first < R->first; }); return Elements; } bool isUTF8(llvm::StringRef S, size_t *ErrOffset) { // Fast-path for ASCII, which is valid UTF-8. if (LLVM_LIKELY(isASCII(S))) return true; const UTF8 *Data = reinterpret_cast<const UTF8 *>(S.data()), *Rest = Data; if (LLVM_LIKELY(isLegalUTF8String(&Rest, Data + S.size()))) return true; if (ErrOffset) *ErrOffset = Rest - Data; return false; } std::string fixUTF8(llvm::StringRef S) { // This isn't particularly efficient, but is only for error-recovery. std::vector<UTF32> Codepoints(S.size()); // 1 codepoint per byte suffices. const UTF8 *In8 = reinterpret_cast<const UTF8 *>(S.data()); UTF32 *Out32 = Codepoints.data(); ConvertUTF8toUTF32(&In8, In8 + S.size(), &Out32, Out32 + Codepoints.size(), lenientConversion); Codepoints.resize(Out32 - Codepoints.data()); std::string Res(4 * Codepoints.size(), 0); // 4 bytes per codepoint suffice const UTF32 *In32 = Codepoints.data(); UTF8 *Out8 = reinterpret_cast<UTF8 *>(&Res[0]); ConvertUTF32toUTF8(&In32, In32 + Codepoints.size(), &Out8, Out8 + Res.size(), strictConversion); Res.resize(reinterpret_cast<char *>(Out8) - Res.data()); return Res; } static void quote(llvm::raw_ostream &OS, llvm::StringRef S) { OS << '\"'; for (unsigned char C : S) { if (C == 0x22 || C == 0x5C) OS << '\\'; if (C >= 0x20) { OS << C; continue; } OS << '\\'; switch (C) { // A few characters are common enough to make short escapes worthwhile. case '\t': OS << 't'; break; case '\n': OS << 'n'; break; case '\r': OS << 'r'; break; default: OS << 'u'; llvm::write_hex(OS, C, llvm::HexPrintStyle::Lower, 4); break; } } OS << '\"'; } void llvm::json::OStream::value(const Value &V) { switch (V.kind()) { case Value::Null: valueBegin(); OS << "null"; return; case Value::Boolean: valueBegin(); OS << (*V.getAsBoolean() ? "true" : "false"); return; case Value::Number: valueBegin(); if (V.Type == Value::T_Integer) OS << *V.getAsInteger(); else OS << format("%.*g", std::numeric_limits<double>::max_digits10, *V.getAsNumber()); return; case Value::String: valueBegin(); quote(OS, *V.getAsString()); return; case Value::Array: return array([&] { for (const Value &E : *V.getAsArray()) value(E); }); case Value::Object: return object([&] { for (const Object::value_type *E : sortedElements(*V.getAsObject())) attribute(E->first, E->second); }); } } void llvm::json::OStream::valueBegin() { assert(Stack.back().Ctx != Object && "Only attributes allowed here"); if (Stack.back().HasValue) { assert(Stack.back().Ctx != Singleton && "Only one value allowed here"); OS << ','; } if (Stack.back().Ctx == Array) newline(); Stack.back().HasValue = true; } void llvm::json::OStream::newline() { if (IndentSize) { OS.write('\n'); OS.indent(Indent); } } void llvm::json::OStream::arrayBegin() { valueBegin(); Stack.emplace_back(); Stack.back().Ctx = Array; Indent += IndentSize; OS << '['; } void llvm::json::OStream::arrayEnd() { assert(Stack.back().Ctx == Array); Indent -= IndentSize; if (Stack.back().HasValue) newline(); OS << ']'; Stack.pop_back(); assert(!Stack.empty()); } void llvm::json::OStream::objectBegin() { valueBegin(); Stack.emplace_back(); Stack.back().Ctx = Object; Indent += IndentSize; OS << '{'; } void llvm::json::OStream::objectEnd() { assert(Stack.back().Ctx == Object); Indent -= IndentSize; if (Stack.back().HasValue) newline(); OS << '}'; Stack.pop_back(); assert(!Stack.empty()); } void llvm::json::OStream::attributeBegin(llvm::StringRef Key) { assert(Stack.back().Ctx == Object); if (Stack.back().HasValue) OS << ','; newline(); Stack.back().HasValue = true; Stack.emplace_back(); Stack.back().Ctx = Singleton; if (LLVM_LIKELY(isUTF8(Key))) { quote(OS, Key); } else { assert(false && "Invalid UTF-8 in attribute key"); quote(OS, fixUTF8(Key)); } OS.write(':'); if (IndentSize) OS.write(' '); } void llvm::json::OStream::attributeEnd() { assert(Stack.back().Ctx == Singleton); assert(Stack.back().HasValue && "Attribute must have a value"); Stack.pop_back(); assert(Stack.back().Ctx == Object); } } // namespace json } // namespace llvm void llvm::format_provider<llvm::json::Value>::format( const llvm::json::Value &E, raw_ostream &OS, StringRef Options) { unsigned IndentAmount = 0; if (!Options.empty() && Options.getAsInteger(/*Radix=*/10, IndentAmount)) llvm_unreachable("json::Value format options should be an integer"); json::OStream(OS, IndentAmount).value(E); }
Upload File
Create Folder