LCOV - code coverage report
Current view: top level - lib/Support - JSON.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 363 383 94.8 %
Date: 2018-10-20 13:21:21 Functions: 36 40 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //=== JSON.cpp - JSON value, parsing and serialization - C++ -----------*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===---------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/Support/JSON.h"
      11             : #include "llvm/Support/ConvertUTF.h"
      12             : #include "llvm/Support/Format.h"
      13             : #include <cctype>
      14             : 
      15             : namespace llvm {
      16             : namespace json {
      17             : 
      18           0 : Value &Object::operator[](const ObjectKey &K) {
      19           0 :   return try_emplace(K, nullptr).first->getSecond();
      20             : }
      21        5911 : Value &Object::operator[](ObjectKey &&K) {
      22        5911 :   return try_emplace(std::move(K), nullptr).first->getSecond();
      23             : }
      24         421 : Value *Object::get(StringRef K) {
      25         421 :   auto I = find(K);
      26         421 :   if (I == end())
      27             :     return nullptr;
      28         272 :   return &I->second;
      29             : }
      30        6053 : const Value *Object::get(StringRef K) const {
      31        6053 :   auto I = find(K);
      32        6053 :   if (I == end())
      33             :     return nullptr;
      34        5716 :   return &I->second;
      35             : }
      36           3 : llvm::Optional<std::nullptr_t> Object::getNull(StringRef K) const {
      37           3 :   if (auto *V = get(K))
      38           2 :     return V->getAsNull();
      39             :   return llvm::None;
      40             : }
      41           6 : llvm::Optional<bool> Object::getBoolean(StringRef K) const {
      42           6 :   if (auto *V = get(K))
      43             :     return V->getAsBoolean();
      44             :   return llvm::None;
      45             : }
      46           1 : llvm::Optional<double> Object::getNumber(StringRef K) const {
      47           1 :   if (auto *V = get(K))
      48             :     return V->getAsNumber();
      49             :   return llvm::None;
      50             : }
      51           1 : llvm::Optional<int64_t> Object::getInteger(StringRef K) const {
      52           1 :   if (auto *V = get(K))
      53           1 :     return V->getAsInteger();
      54             :   return llvm::None;
      55             : }
      56        1722 : llvm::Optional<llvm::StringRef> Object::getString(StringRef K) const {
      57        1722 :   if (auto *V = get(K))
      58             :     return V->getAsString();
      59             :   return llvm::None;
      60             : }
      61          98 : const json::Object *Object::getObject(StringRef K) const {
      62          98 :   if (auto *V = get(K))
      63             :     return V->getAsObject();
      64             :   return nullptr;
      65             : }
      66           4 : json::Object *Object::getObject(StringRef K) {
      67           4 :   if (auto *V = get(K))
      68             :     return V->getAsObject();
      69             :   return nullptr;
      70             : }
      71        1058 : const json::Array *Object::getArray(StringRef K) const {
      72        1058 :   if (auto *V = get(K))
      73             :     return V->getAsArray();
      74             :   return nullptr;
      75             : }
      76           1 : json::Array *Object::getArray(StringRef K) {
      77           1 :   if (auto *V = get(K))
      78             :     return V->getAsArray();
      79             :   return nullptr;
      80             : }
      81           6 : bool operator==(const Object &LHS, const Object &RHS) {
      82           6 :   if (LHS.size() != RHS.size())
      83             :     return false;
      84          12 :   for (const auto &L : LHS) {
      85           6 :     auto R = RHS.find(L.first);
      86           6 :     if (R == RHS.end() || L.second != R->second)
      87             :       return false;
      88             :   }
      89           6 :   return true;
      90             : }
      91             : 
      92         518 : Array::Array(std::initializer_list<Value> Elements) {
      93         518 :   V.reserve(Elements.size());
      94        2940 :   for (const Value &V : Elements) {
      95        2422 :     emplace_back(nullptr);
      96        2422 :     back().moveFrom(std::move(V));
      97             :   }
      98         518 : }
      99             : 
     100         175 : Value::Value(std::initializer_list<Value> Elements)
     101         175 :     : Value(json::Array(Elements)) {}
     102             : 
     103       10886 : void Value::copyFrom(const Value &M) {
     104       10886 :   Type = M.Type;
     105       10886 :   switch (Type) {
     106        5537 :   case T_Null:
     107             :   case T_Boolean:
     108             :   case T_Double:
     109             :   case T_Integer:
     110        5537 :     memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
     111        5537 :     break;
     112             :   case T_StringRef:
     113             :     create<StringRef>(M.as<StringRef>());
     114          14 :     break;
     115             :   case T_String:
     116             :     create<std::string>(M.as<std::string>());
     117             :     break;
     118             :   case T_Object:
     119             :     create<json::Object>(M.as<json::Object>());
     120             :     break;
     121             :   case T_Array:
     122        1109 :     create<json::Array>(M.as<json::Array>());
     123        1109 :     break;
     124             :   }
     125       10886 : }
     126             : 
     127       16759 : void Value::moveFrom(const Value &&M) {
     128       16759 :   Type = M.Type;
     129       16759 :   switch (Type) {
     130        5534 :   case T_Null:
     131             :   case T_Boolean:
     132             :   case T_Double:
     133             :   case T_Integer:
     134        5534 :     memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
     135        5534 :     break;
     136             :   case T_StringRef:
     137             :     create<StringRef>(M.as<StringRef>());
     138         585 :     break;
     139             :   case T_String:
     140             :     create<std::string>(std::move(M.as<std::string>()));
     141        4471 :     M.Type = T_Null;
     142        4471 :     break;
     143             :   case T_Object:
     144             :     create<json::Object>(std::move(M.as<json::Object>()));
     145        4541 :     M.Type = T_Null;
     146        4541 :     break;
     147             :   case T_Array:
     148             :     create<json::Array>(std::move(M.as<json::Array>()));
     149        1628 :     M.Type = T_Null;
     150        1628 :     break;
     151             :   }
     152       16759 : }
     153             : 
     154       49921 : void Value::destroy() {
     155       49921 :   switch (Type) {
     156             :   case T_Null:
     157             :   case T_Boolean:
     158             :   case T_Double:
     159             :   case T_Integer:
     160             :     break;
     161             :   case T_StringRef:
     162             :     as<StringRef>().~StringRef();
     163             :     break;
     164             :   case T_String:
     165             :     as<std::string>().~basic_string();
     166             :     break;
     167             :   case T_Object:
     168             :     as<json::Object>().~Object();
     169             :     break;
     170             :   case T_Array:
     171        2693 :     as<json::Array>().~Array();
     172        2693 :     break;
     173             :   }
     174       49921 : }
     175             : 
     176          35 : bool operator==(const Value &L, const Value &R) {
     177          35 :   if (L.kind() != R.kind())
     178             :     return false;
     179          35 :   switch (L.kind()) {
     180             :   case Value::Null:
     181             :     return *L.getAsNull() == *R.getAsNull();
     182             :   case Value::Boolean:
     183           4 :     return *L.getAsBoolean() == *R.getAsBoolean();
     184             :   case Value::Number:
     185          13 :     return *L.getAsNumber() == *R.getAsNumber();
     186             :   case Value::String:
     187           8 :     return *L.getAsString() == *R.getAsString();
     188             :   case Value::Array:
     189           6 :     return *L.getAsArray() == *R.getAsArray();
     190             :   case Value::Object:
     191           5 :     return *L.getAsObject() == *R.getAsObject();
     192             :   }
     193           0 :   llvm_unreachable("Unknown value kind");
     194             : }
     195             : 
     196             : namespace {
     197             : // Simple recursive-descent JSON parser.
     198             : class Parser {
     199             : public:
     200             :   Parser(StringRef JSON)
     201         888 :       : Start(JSON.begin()), P(JSON.begin()), End(JSON.end()) {}
     202             : 
     203         444 :   bool checkUTF8() {
     204             :     size_t ErrOffset;
     205         888 :     if (isUTF8(StringRef(Start, End - Start), &ErrOffset))
     206             :       return true;
     207           1 :     P = Start + ErrOffset; // For line/column calculation.
     208           1 :     return parseError("Invalid UTF-8 sequence");
     209             :   }
     210             : 
     211             :   bool parseValue(Value &Out);
     212             : 
     213         427 :   bool assertEnd() {
     214         427 :     eatWhitespace();
     215         427 :     if (P == End)
     216             :       return true;
     217           1 :     return parseError("Text after end of document");
     218             :   }
     219             : 
     220             :   Error takeError() {
     221             :     assert(Err);
     222             :     return std::move(*Err);
     223             :   }
     224             : 
     225             : private:
     226           0 :   void eatWhitespace() {
     227      111028 :     while (P != End && (*P == ' ' || *P == '\r' || *P == '\n' || *P == '\t'))
     228       78979 :       ++P;
     229           0 :   }
     230             : 
     231             :   // On invalid syntax, parseX() functions return false and set Err.
     232             :   bool parseNumber(char First, Value &Out);
     233             :   bool parseString(std::string &Out);
     234             :   bool parseUnicode(std::string &Out);
     235             :   bool parseError(const char *Msg); // always returns false
     236             : 
     237       21870 :   char next() { return P == End ? 0 : *P++; }
     238        3531 :   char peek() { return P == End ? 0 : *P; }
     239             :   static bool isNumber(char C) {
     240             :     return C == '0' || C == '1' || C == '2' || C == '3' || C == '4' ||
     241        2252 :            C == '5' || C == '6' || C == '7' || C == '8' || C == '9' ||
     242         704 :            C == 'e' || C == 'E' || C == '+' || C == '-' || C == '.';
     243             :   }
     244             : 
     245             :   Optional<Error> Err;
     246             :   const char *Start, *P, *End;
     247             : };
     248             : 
     249        7269 : bool Parser::parseValue(Value &Out) {
     250        7269 :   eatWhitespace();
     251        7269 :   if (P == End)
     252           2 :     return parseError("Unexpected EOF");
     253        7267 :   switch (char C = next()) {
     254             :   // Bare null/true/false are easy - first char identifies them.
     255             :   case 'n':
     256           3 :     Out = nullptr;
     257           9 :     return (next() == 'u' && next() == 'l' && next() == 'l') ||
     258           0 :            parseError("Invalid JSON value (null?)");
     259             :   case 't':
     260          14 :     Out = true;
     261          42 :     return (next() == 'r' && next() == 'u' && next() == 'e') ||
     262           0 :            parseError("Invalid JSON value (true?)");
     263             :   case 'f':
     264           3 :     Out = false;
     265          10 :     return (next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') ||
     266           1 :            parseError("Invalid JSON value (false?)");
     267             :   case '"': {
     268             :     std::string S;
     269        3984 :     if (parseString(S)) {
     270        7960 :       Out = std::move(S);
     271        3980 :       return true;
     272             :     }
     273             :     return false;
     274             :   }
     275         827 :   case '[': {
     276         827 :     Out = Array{};
     277             :     Array &A = *Out.getAsArray();
     278         827 :     eatWhitespace();
     279         826 :     if (peek() == ']') {
     280           4 :       ++P;
     281           4 :       return true;
     282             :     }
     283             :     for (;;) {
     284        1499 :       A.emplace_back(nullptr);
     285        1499 :       if (!parseValue(A.back()))
     286             :         return false;
     287        1497 :       eatWhitespace();
     288        1497 :       switch (next()) {
     289             :       case ',':
     290             :         eatWhitespace();
     291             :         continue;
     292             :       case ']':
     293             :         return true;
     294           1 :       default:
     295           1 :         return parseError("Expected , or ] after array element");
     296             :       }
     297             :     }
     298             :   }
     299        2012 :   case '{': {
     300        4024 :     Out = Object{};
     301             :     Object &O = *Out.getAsObject();
     302        2012 :     eatWhitespace();
     303        2012 :     if (peek() == '}') {
     304          37 :       ++P;
     305          37 :       return true;
     306             :     }
     307             :     for (;;) {
     308        5332 :       if (next() != '"')
     309        1975 :         return parseError("Expected object key");
     310             :       std::string K;
     311        5330 :       if (!parseString(K))
     312             :         return false;
     313        5330 :       eatWhitespace();
     314        5328 :       if (next() != ':')
     315           3 :         return parseError("Expected : after object key");
     316             :       eatWhitespace();
     317       10654 :       if (!parseValue(O[std::move(K)]))
     318             :         return false;
     319        5327 :       eatWhitespace();
     320        5327 :       switch (next()) {
     321             :       case ',':
     322             :         eatWhitespace();
     323             :         continue;
     324             :       case '}':
     325             :         return true;
     326           1 :       default:
     327           1 :         return parseError("Expected , or } after object property");
     328             :       }
     329             :     }
     330             :   }
     331         424 :   default:
     332         424 :     if (isNumber(C))
     333         423 :       return parseNumber(C, Out);
     334           1 :     return parseError("Invalid JSON value");
     335             :   }
     336             : }
     337             : 
     338         423 : bool Parser::parseNumber(char First, Value &Out) {
     339             :   // Read the number into a string. (Must be null-terminated for strto*).
     340             :   SmallString<24> S;
     341         423 :   S.push_back(First);
     342         702 :   while (isNumber(peek()))
     343         279 :     S.push_back(next());
     344             :   char *End;
     345             :   // Try first to parse as integer, and if so preserve full 64 bits.
     346             :   // strtoll returns long long >= 64 bits, so check it's in range too.
     347         423 :   auto I = std::strtoll(S.c_str(), &End, 10);
     348         423 :   if (End == S.end() && I >= std::numeric_limits<int64_t>::min() &&
     349             :       I <= std::numeric_limits<int64_t>::max()) {
     350         414 :     Out = int64_t(I);
     351         414 :     return true;
     352             :   }
     353             :   // If it's not an integer
     354          18 :   Out = std::strtod(S.c_str(), &End);
     355           9 :   return End == S.end() || parseError("Invalid JSON value (number?)");
     356             : }
     357             : 
     358        9314 : bool Parser::parseString(std::string &Out) {
     359             :   // leading quote was already consumed.
     360      138791 :   for (char C = next(); C != '"'; C = next()) {
     361      120167 :     if (LLVM_UNLIKELY(P == End))
     362           1 :       return parseError("Unterminated string");
     363      120166 :     if (LLVM_UNLIKELY((C & 0x1f) == C))
     364           1 :       return parseError("Control character in string");
     365      120165 :     if (LLVM_LIKELY(C != '\\')) {
     366      120082 :       Out.push_back(C);
     367      120082 :       continue;
     368             :     }
     369             :     // Handle escape sequence.
     370          83 :     switch (C = next()) {
     371           9 :     case '"':
     372             :     case '\\':
     373             :     case '/':
     374           9 :       Out.push_back(C);
     375           9 :       break;
     376           1 :     case 'b':
     377           1 :       Out.push_back('\b');
     378           1 :       break;
     379           1 :     case 'f':
     380           1 :       Out.push_back('\f');
     381           1 :       break;
     382          62 :     case 'n':
     383          62 :       Out.push_back('\n');
     384          62 :       break;
     385           1 :     case 'r':
     386           1 :       Out.push_back('\r');
     387           1 :       break;
     388           1 :     case 't':
     389           1 :       Out.push_back('\t');
     390           1 :       break;
     391           7 :     case 'u':
     392           7 :       if (!parseUnicode(Out))
     393             :         return false;
     394             :       break;
     395           1 :     default:
     396           1 :       return parseError("Invalid escape sequence");
     397             :     }
     398             :   }
     399             :   return true;
     400             : }
     401             : 
     402           4 : static void encodeUtf8(uint32_t Rune, std::string &Out) {
     403           4 :   if (Rune < 0x80) {
     404           2 :     Out.push_back(Rune & 0x7F);
     405           2 :   } else if (Rune < 0x800) {
     406           0 :     uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
     407           0 :     uint8_t SecondByte = 0x80 | (Rune & 0x3F);
     408           0 :     Out.push_back(FirstByte);
     409           0 :     Out.push_back(SecondByte);
     410           2 :   } else if (Rune < 0x10000) {
     411           0 :     uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
     412           0 :     uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
     413           0 :     uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
     414           0 :     Out.push_back(FirstByte);
     415           0 :     Out.push_back(SecondByte);
     416           0 :     Out.push_back(ThirdByte);
     417           2 :   } else if (Rune < 0x110000) {
     418           2 :     uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
     419           2 :     uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
     420           2 :     uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
     421           2 :     uint8_t FourthByte = 0x80 | (Rune & 0x3F);
     422           2 :     Out.push_back(FirstByte);
     423           2 :     Out.push_back(SecondByte);
     424           2 :     Out.push_back(ThirdByte);
     425           2 :     Out.push_back(FourthByte);
     426             :   } else {
     427           0 :     llvm_unreachable("Invalid codepoint");
     428             :   }
     429           4 : }
     430             : 
     431             : // Parse a UTF-16 \uNNNN escape sequence. "\u" has already been consumed.
     432             : // May parse several sequential escapes to ensure proper surrogate handling.
     433             : // We do not use ConvertUTF.h, it can't accept and replace unpaired surrogates.
     434             : // These are invalid Unicode but valid JSON (RFC 8259, section 8.2).
     435           7 : bool Parser::parseUnicode(std::string &Out) {
     436             :   // Invalid UTF is not a JSON error (RFC 8529ยง8.2). It gets replaced by U+FFFD.
     437             :   auto Invalid = [&] { Out.append(/* UTF-8 */ {'\xef', '\xbf', '\xbd'}); };
     438             :   // Decodes 4 hex digits from the stream into Out, returns false on error.
     439             :   auto Parse4Hex = [this](uint16_t &Out) -> bool {
     440             :     Out = 0;
     441             :     char Bytes[] = {next(), next(), next(), next()};
     442             :     for (unsigned char C : Bytes) {
     443             :       if (!std::isxdigit(C))
     444             :         return parseError("Invalid \\u escape sequence");
     445             :       Out <<= 4;
     446             :       Out |= (C > '9') ? (C & ~0x20) - 'A' + 10 : (C - '0');
     447             :     }
     448             :     return true;
     449             :   };
     450             :   uint16_t First; // UTF-16 code unit from the first \u escape.
     451           7 :   if (!Parse4Hex(First))
     452             :     return false;
     453             : 
     454             :   // We loop to allow proper surrogate-pair error handling.
     455             :   while (true) {
     456             :     // Case 1: the UTF-16 code unit is already a codepoint in the BMP.
     457           7 :     if (LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) {
     458           2 :       encodeUtf8(First, Out);
     459           6 :       return true;
     460             :     }
     461             : 
     462             :     // Case 2: it's an (unpaired) trailing surrogate.
     463           5 :     if (LLVM_UNLIKELY(First >= 0xDC00)) {
     464             :       Invalid();
     465           1 :       return true;
     466             :     }
     467             : 
     468             :     // Case 3: it's a leading surrogate. We expect a trailing one next.
     469             :     // Case 3a: there's no trailing \u escape. Don't advance in the stream.
     470           4 :     if (LLVM_UNLIKELY(P + 2 > End || *P != '\\' || *(P + 1) != 'u')) {
     471             :       Invalid(); // Leading surrogate was unpaired.
     472           1 :       return true;
     473             :     }
     474           3 :     P += 2;
     475             :     uint16_t Second;
     476           3 :     if (!Parse4Hex(Second))
     477             :       return false;
     478             :     // Case 3b: there was another \u escape, but it wasn't a trailing surrogate.
     479           3 :     if (LLVM_UNLIKELY(Second < 0xDC00 || Second >= 0xE000)) {
     480             :       Invalid();      // Leading surrogate was unpaired.
     481           1 :       First = Second; // Second escape still needs to be processed.
     482           1 :       continue;
     483             :     }
     484             :     // Case 3c: a valid surrogate pair encoding an astral codepoint.
     485           2 :     encodeUtf8(0x10000 | ((First - 0xD800) << 10) | (Second - 0xDC00), Out);
     486           2 :     return true;
     487             :   }
     488             : }
     489             : 
     490          18 : bool Parser::parseError(const char *Msg) {
     491             :   int Line = 1;
     492          18 :   const char *StartOfLine = Start;
     493         112 :   for (const char *X = Start; X < P; ++X) {
     494          94 :     if (*X == 0x0A) {
     495           3 :       ++Line;
     496           3 :       StartOfLine = X + 1;
     497             :     }
     498             :   }
     499             :   Err.emplace(
     500          18 :       llvm::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start));
     501          18 :   return false;
     502             : }
     503             : } // namespace
     504             : 
     505         444 : Expected<Value> parse(StringRef JSON) {
     506             :   Parser P(JSON);
     507             :   Value E = nullptr;
     508         444 :   if (P.checkUTF8())
     509         443 :     if (P.parseValue(E))
     510         427 :       if (P.assertEnd())
     511             :         return std::move(E);
     512             :   return P.takeError();
     513             : }
     514             : char ParseError::ID = 0;
     515             : 
     516        1285 : static std::vector<const Object::value_type *> sortedElements(const Object &O) {
     517             :   std::vector<const Object::value_type *> Elements;
     518        5114 :   for (const auto &E : O)
     519        3829 :     Elements.push_back(&E);
     520             :   llvm::sort(Elements,
     521             :              [](const Object::value_type *L, const Object::value_type *R) {
     522             :                return L->first < R->first;
     523             :              });
     524        1285 :   return Elements;
     525             : }
     526             : 
     527      174406 : bool isUTF8(llvm::StringRef S, size_t *ErrOffset) {
     528             :   // Fast-path for ASCII, which is valid UTF-8.
     529      174406 :   if (LLVM_LIKELY(isASCII(S)))
     530             :     return true;
     531             : 
     532          21 :   const UTF8 *Data = reinterpret_cast<const UTF8 *>(S.data()), *Rest = Data;
     533          21 :   if (LLVM_LIKELY(isLegalUTF8String(&Rest, Data + S.size())))
     534             :     return true;
     535             : 
     536           9 :   if (ErrOffset)
     537           1 :     *ErrOffset = Rest - Data;
     538             :   return false;
     539             : }
     540             : 
     541          11 : std::string fixUTF8(llvm::StringRef S) {
     542             :   // This isn't particularly efficient, but is only for error-recovery.
     543          11 :   std::vector<UTF32> Codepoints(S.size()); // 1 codepoint per byte suffices.
     544          11 :   const UTF8 *In8 = reinterpret_cast<const UTF8 *>(S.data());
     545          11 :   UTF32 *Out32 = Codepoints.data();
     546          11 :   ConvertUTF8toUTF32(&In8, In8 + S.size(), &Out32, Out32 + Codepoints.size(),
     547             :                      lenientConversion);
     548          11 :   Codepoints.resize(Out32 - Codepoints.data());
     549          22 :   std::string Res(4 * Codepoints.size(), 0); // 4 bytes per codepoint suffice
     550          11 :   const UTF32 *In32 = Codepoints.data();
     551          11 :   UTF8 *Out8 = reinterpret_cast<UTF8 *>(&Res[0]);
     552          11 :   ConvertUTF32toUTF8(&In32, In32 + Codepoints.size(), &Out8, Out8 + Res.size(),
     553             :                      strictConversion);
     554          22 :   Res.resize(reinterpret_cast<char *>(Out8) - Res.data());
     555          11 :   return Res;
     556             : }
     557             : 
     558             : } // namespace json
     559             : } // namespace llvm
     560             : 
     561        4936 : static void quote(llvm::raw_ostream &OS, llvm::StringRef S) {
     562             :   OS << '\"';
     563       52417 :   for (unsigned char C : S) {
     564       47481 :     if (C == 0x22 || C == 0x5C)
     565             :       OS << '\\';
     566       47481 :     if (C >= 0x20) {
     567       47441 :       OS << C;
     568       47441 :       continue;
     569             :     }
     570             :     OS << '\\';
     571          40 :     switch (C) {
     572             :     // A few characters are common enough to make short escapes worthwhile.
     573             :     case '\t':
     574             :       OS << 't';
     575             :       break;
     576             :     case '\n':
     577             :       OS << 'n';
     578             :       break;
     579             :     case '\r':
     580             :       OS << 'r';
     581             :       break;
     582             :     default:
     583             :       OS << 'u';
     584          11 :       llvm::write_hex(OS, C, llvm::HexPrintStyle::Lower, 4);
     585          11 :       break;
     586             :     }
     587             :   }
     588             :   OS << '\"';
     589        4936 : }
     590             : 
     591             : enum IndenterAction {
     592             :   Indent,
     593             :   Outdent,
     594             :   Newline,
     595             :   Space,
     596             : };
     597             : 
     598             : // Prints JSON. The indenter can be used to control formatting.
     599             : template <typename Indenter>
     600        7497 : void llvm::json::Value::print(raw_ostream &OS, const Indenter &I) const {
     601        7497 :   switch (Type) {
     602          80 :   case T_Null:
     603          80 :     OS << "null";
     604          80 :     break;
     605             :   case T_Boolean:
     606         957 :     OS << (as<bool>() ? "true" : "false");
     607         785 :     break;
     608             :   case T_Double:
     609         318 :     OS << format("%.*g", std::numeric_limits<double>::max_digits10,
     610             :                  as<double>());
     611         159 :     break;
     612             :   case T_Integer:
     613        3323 :     OS << as<int64_t>();
     614        3323 :     break;
     615             :   case T_StringRef:
     616         574 :     quote(OS, as<StringRef>());
     617         574 :     break;
     618             :   case T_String:
     619         533 :     quote(OS, as<std::string>());
     620         533 :     break;
     621        1285 :   case T_Object: {
     622             :     bool Comma = false;
     623             :     OS << '{';
     624             :     I(Indent);
     625        6399 :     for (const auto *P : sortedElements(as<json::Object>())) {
     626        3829 :       if (Comma)
     627             :         OS << ',';
     628             :       Comma = true;
     629        2911 :       I(Newline);
     630        3829 :       quote(OS, P->first);
     631             :       OS << ':';
     632        2911 :       I(Space);
     633        3829 :       P->second.print(OS, I);
     634             :     }
     635             :     I(Outdent);
     636        1031 :     if (Comma)
     637        1023 :       I(Newline);
     638             :     OS << '}';
     639             :     break;
     640             :   }
     641         758 :   case T_Array: {
     642             :     bool Comma = false;
     643             :     OS << '[';
     644             :     I(Indent);
     645        3768 :     for (const auto &E : as<json::Array>()) {
     646        3010 :       if (Comma)
     647             :         OS << ',';
     648             :       Comma = true;
     649         350 :       I(Newline);
     650        3010 :       E.print(OS, I);
     651             :     }
     652             :     I(Outdent);
     653         249 :     if (Comma)
     654         189 :       I(Newline);
     655             :     OS << ']';
     656             :     break;
     657             :   }
     658             :   }
     659        7497 : }
     660        4008 : 
     661        4008 : void llvm::format_provider<llvm::json::Value>::format(
     662          41 :     const llvm::json::Value &E, raw_ostream &OS, StringRef Options) {
     663          41 :   if (Options.empty()) {
     664          41 :     OS << E;
     665             :     return;
     666         479 :   }
     667         360 :   unsigned IndentAmount = 0;
     668             :   if (Options.getAsInteger(/*Radix=*/10, IndentAmount))
     669         244 :     llvm_unreachable("json::Value format options should be an integer");
     670             :   unsigned IndentLevel = 0;
     671         122 :   E.print(OS, [&](IndenterAction A) {
     672             :     switch (A) {
     673        2545 :     case Newline:
     674        2545 :       OS << '\n';
     675             :       OS.indent(IndentLevel);
     676          53 :       break;
     677          53 :     case Space:
     678             :       OS << ' ';
     679         124 :       break;
     680         124 :     case Indent:
     681         254 :       IndentLevel += IndentAmount;
     682             :       break;
     683             :     case Outdent:
     684             :       IndentLevel -= IndentAmount;
     685        1426 :       break;
     686         918 :     };
     687             :   });
     688             : }
     689             : 
     690         918 : llvm::raw_ostream &llvm::json::operator<<(raw_ostream &OS, const Value &E) {
     691             :   E.print(OS, [](IndenterAction A) { /*ignore*/ });
     692             :   return OS;
     693         918 : }

Generated by: LCOV version 1.13