1 //===--- JSON.h - JSON values, 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 /// \file 11 /// This file supports working with JSON data. 12 /// 13 /// It comprises: 14 /// 15 /// - classes which hold dynamically-typed parsed JSON structures 16 /// These are value types that can be composed, inspected, and modified. 17 /// See json::Value, and the related types json::Object and json::Array. 18 /// 19 /// - functions to parse JSON text into Values, and to serialize Values to text. 20 /// See parse(), operator<<, and format_provider. 21 /// 22 /// - a convention and helpers for mapping between json::Value and user-defined 23 /// types. See fromJSON(), ObjectMapper, and the class comment on Value. 24 /// 25 /// Typically, JSON data would be read from an external source, parsed into 26 /// a Value, and then converted into some native data structure before doing 27 /// real work on it. (And vice versa when writing). 28 /// 29 /// Other serialization mechanisms you may consider: 30 /// 31 /// - YAML is also text-based, and more human-readable than JSON. It's a more 32 /// complex format and data model, and YAML parsers aren't ubiquitous. 33 /// YAMLParser.h is a streaming parser suitable for parsing large documents 34 /// (including JSON, as YAML is a superset). It can be awkward to use 35 /// directly. YAML I/O (YAMLTraits.h) provides data mapping that is more 36 /// declarative than the toJSON/fromJSON conventions here. 37 /// 38 /// - LLVM bitstream is a space- and CPU- efficient binary format. Typically it 39 /// encodes LLVM IR ("bitcode"), but it can be a container for other data. 40 /// Low-level reader/writer libraries are in Bitcode/Bitstream*.h 41 /// 42 //===---------------------------------------------------------------------===// 43 44 #ifndef LLVM_SUPPORT_JSON_H 45 #define LLVM_SUPPORT_JSON_H 46 47 #include "llvm/ADT/DenseMap.h" 48 #include "llvm/ADT/SmallVector.h" 49 #include "llvm/ADT/StringRef.h" 50 #include "llvm/Support/Error.h" 51 #include "llvm/Support/FormatVariadic.h" 52 #include "llvm/Support/raw_ostream.h" 53 #include <map> 54 55 namespace llvm { 56 namespace json { 57 58 // === String encodings === 59 // 60 // JSON strings are character sequences (not byte sequences like std::string). 61 // We need to know the encoding, and for simplicity only support UTF-8. 62 // 63 // - When parsing, invalid UTF-8 is a syntax error like any other 64 // 65 // - When creating Values from strings, callers must ensure they are UTF-8. 66 // with asserts on, invalid UTF-8 will crash the program 67 // with asserts off, we'll substitute the replacement character (U+FFFD) 68 // Callers can use json::isUTF8() and json::fixUTF8() for validation. 69 // 70 // - When retrieving strings from Values (e.g. asString()), the result will 71 // always be valid UTF-8. 72 73 /// Returns true if \p S is valid UTF-8, which is required for use as JSON. 74 /// If it returns false, \p Offset is set to a byte offset near the first error. 75 bool isUTF8(llvm::StringRef S, size_t *ErrOffset = nullptr); 76 /// Replaces invalid UTF-8 sequences in \p S with the replacement character 77 /// (U+FFFD). The returned string is valid UTF-8. 78 /// This is much slower than isUTF8, so test that first. 79 std::string fixUTF8(llvm::StringRef S); 80 81 class Array; 82 class ObjectKey; 83 class Value; 84 template <typename T> Value toJSON(const llvm::Optional<T> &Opt); 85 86 /// An Object is a JSON object, which maps strings to heterogenous JSON values. 87 /// It simulates DenseMap<ObjectKey, Value>. ObjectKey is a maybe-owned string. 88 class Object { 89 using Storage = DenseMap<ObjectKey, Value, llvm::DenseMapInfo<StringRef>>; 90 Storage M; 91 92 public: 93 using key_type = ObjectKey; 94 using mapped_type = Value; 95 using value_type = Storage::value_type; 96 using iterator = Storage::iterator; 97 using const_iterator = Storage::const_iterator; 98 99 explicit Object() = default; 100 // KV is a trivial key-value struct for list-initialization. 101 // (using std::pair forces extra copies). 102 struct KV; 103 explicit Object(std::initializer_list<KV> Properties); 104 begin()105 iterator begin() { return M.begin(); } begin()106 const_iterator begin() const { return M.begin(); } end()107 iterator end() { return M.end(); } end()108 const_iterator end() const { return M.end(); } 109 empty()110 bool empty() const { return M.empty(); } size()111 size_t size() const { return M.size(); } 112 clear()113 void clear() { M.clear(); } 114 std::pair<iterator, bool> insert(KV E); 115 template <typename... Ts> try_emplace(const ObjectKey & K,Ts &&...Args)116 std::pair<iterator, bool> try_emplace(const ObjectKey &K, Ts &&... Args) { 117 return M.try_emplace(K, std::forward<Ts>(Args)...); 118 } 119 template <typename... Ts> try_emplace(ObjectKey && K,Ts &&...Args)120 std::pair<iterator, bool> try_emplace(ObjectKey &&K, Ts &&... Args) { 121 return M.try_emplace(std::move(K), std::forward<Ts>(Args)...); 122 } 123 find(StringRef K)124 iterator find(StringRef K) { return M.find_as(K); } find(StringRef K)125 const_iterator find(StringRef K) const { return M.find_as(K); } 126 // operator[] acts as if Value was default-constructible as null. 127 Value &operator[](const ObjectKey &K); 128 Value &operator[](ObjectKey &&K); 129 // Look up a property, returning nullptr if it doesn't exist. 130 Value *get(StringRef K); 131 const Value *get(StringRef K) const; 132 // Typed accessors return None/nullptr if 133 // - the property doesn't exist 134 // - or it has the wrong type 135 llvm::Optional<std::nullptr_t> getNull(StringRef K) const; 136 llvm::Optional<bool> getBoolean(StringRef K) const; 137 llvm::Optional<double> getNumber(StringRef K) const; 138 llvm::Optional<int64_t> getInteger(StringRef K) const; 139 llvm::Optional<llvm::StringRef> getString(StringRef K) const; 140 const json::Object *getObject(StringRef K) const; 141 json::Object *getObject(StringRef K); 142 const json::Array *getArray(StringRef K) const; 143 json::Array *getArray(StringRef K); 144 }; 145 bool operator==(const Object &LHS, const Object &RHS); 146 inline bool operator!=(const Object &LHS, const Object &RHS) { 147 return !(LHS == RHS); 148 } 149 150 /// An Array is a JSON array, which contains heterogeneous JSON values. 151 /// It simulates std::vector<Value>. 152 class Array { 153 std::vector<Value> V; 154 155 public: 156 using value_type = Value; 157 using iterator = std::vector<Value>::iterator; 158 using const_iterator = std::vector<Value>::const_iterator; 159 160 explicit Array() = default; 161 explicit Array(std::initializer_list<Value> Elements); Array(const Collection & C)162 template <typename Collection> explicit Array(const Collection &C) { 163 for (const auto &V : C) 164 emplace_back(V); 165 } 166 167 Value &operator[](size_t I) { return V[I]; } 168 const Value &operator[](size_t I) const { return V[I]; } front()169 Value &front() { return V.front(); } front()170 const Value &front() const { return V.front(); } back()171 Value &back() { return V.back(); } back()172 const Value &back() const { return V.back(); } data()173 Value *data() { return V.data(); } data()174 const Value *data() const { return V.data(); } 175 begin()176 iterator begin() { return V.begin(); } begin()177 const_iterator begin() const { return V.begin(); } end()178 iterator end() { return V.end(); } end()179 const_iterator end() const { return V.end(); } 180 empty()181 bool empty() const { return V.empty(); } size()182 size_t size() const { return V.size(); } 183 clear()184 void clear() { V.clear(); } push_back(const Value & E)185 void push_back(const Value &E) { V.push_back(E); } push_back(Value && E)186 void push_back(Value &&E) { V.push_back(std::move(E)); } emplace_back(Args &&...A)187 template <typename... Args> void emplace_back(Args &&... A) { 188 V.emplace_back(std::forward<Args>(A)...); 189 } pop_back()190 void pop_back() { V.pop_back(); } 191 // FIXME: insert() takes const_iterator since C++11, old libstdc++ disagrees. insert(iterator P,const Value & E)192 iterator insert(iterator P, const Value &E) { return V.insert(P, E); } insert(iterator P,Value && E)193 iterator insert(iterator P, Value &&E) { 194 return V.insert(P, std::move(E)); 195 } insert(iterator P,It A,It Z)196 template <typename It> iterator insert(iterator P, It A, It Z) { 197 return V.insert(P, A, Z); 198 } emplace(const_iterator P,Args &&...A)199 template <typename... Args> iterator emplace(const_iterator P, Args &&... A) { 200 return V.emplace(P, std::forward<Args>(A)...); 201 } 202 203 friend bool operator==(const Array &L, const Array &R) { return L.V == R.V; } 204 }; 205 inline bool operator!=(const Array &L, const Array &R) { return !(L == R); } 206 207 /// A Value is an JSON value of unknown type. 208 /// They can be copied, but should generally be moved. 209 /// 210 /// === Composing values === 211 /// 212 /// You can implicitly construct Values from: 213 /// - strings: std::string, SmallString, formatv, StringRef, char* 214 /// (char*, and StringRef are references, not copies!) 215 /// - numbers 216 /// - booleans 217 /// - null: nullptr 218 /// - arrays: {"foo", 42.0, false} 219 /// - serializable things: types with toJSON(const T&)->Value, found by ADL 220 /// 221 /// They can also be constructed from object/array helpers: 222 /// - json::Object is a type like map<ObjectKey, Value> 223 /// - json::Array is a type like vector<Value> 224 /// These can be list-initialized, or used to build up collections in a loop. 225 /// json::ary(Collection) converts all items in a collection to Values. 226 /// 227 /// === Inspecting values === 228 /// 229 /// Each Value is one of the JSON kinds: 230 /// null (nullptr_t) 231 /// boolean (bool) 232 /// number (double or int64) 233 /// string (StringRef) 234 /// array (json::Array) 235 /// object (json::Object) 236 /// 237 /// The kind can be queried directly, or implicitly via the typed accessors: 238 /// if (Optional<StringRef> S = E.getAsString() 239 /// assert(E.kind() == Value::String); 240 /// 241 /// Array and Object also have typed indexing accessors for easy traversal: 242 /// Expected<Value> E = parse(R"( {"options": {"font": "sans-serif"}} )"); 243 /// if (Object* O = E->getAsObject()) 244 /// if (Object* Opts = O->getObject("options")) 245 /// if (Optional<StringRef> Font = Opts->getString("font")) 246 /// assert(Opts->at("font").kind() == Value::String); 247 /// 248 /// === Converting JSON values to C++ types === 249 /// 250 /// The convention is to have a deserializer function findable via ADL: 251 /// fromJSON(const json::Value&, T&)->bool 252 /// Deserializers are provided for: 253 /// - bool 254 /// - int and int64_t 255 /// - double 256 /// - std::string 257 /// - vector<T>, where T is deserializable 258 /// - map<string, T>, where T is deserializable 259 /// - Optional<T>, where T is deserializable 260 /// ObjectMapper can help writing fromJSON() functions for object types. 261 /// 262 /// For conversion in the other direction, the serializer function is: 263 /// toJSON(const T&) -> json::Value 264 /// If this exists, then it also allows constructing Value from T, and can 265 /// be used to serialize vector<T>, map<string, T>, and Optional<T>. 266 /// 267 /// === Serialization === 268 /// 269 /// Values can be serialized to JSON: 270 /// 1) raw_ostream << Value // Basic formatting. 271 /// 2) raw_ostream << formatv("{0}", Value) // Basic formatting. 272 /// 3) raw_ostream << formatv("{0:2}", Value) // Pretty-print with indent 2. 273 /// 274 /// And parsed: 275 /// Expected<Value> E = json::parse("[1, 2, null]"); 276 /// assert(E && E->kind() == Value::Array); 277 class Value { 278 public: 279 enum Kind { 280 Null, 281 Boolean, 282 /// Number values can store both int64s and doubles at full precision, 283 /// depending on what they were constructed/parsed from. 284 Number, 285 String, 286 Array, 287 Object, 288 }; 289 290 // It would be nice to have Value() be null. But that would make {} null too. Value(const Value & M)291 Value(const Value &M) { copyFrom(M); } Value(Value && M)292 Value(Value &&M) { moveFrom(std::move(M)); } 293 Value(std::initializer_list<Value> Elements); Value(json::Array && Elements)294 Value(json::Array &&Elements) : Type(T_Array) { 295 create<json::Array>(std::move(Elements)); 296 } 297 template <typename Elt> Value(const std::vector<Elt> & C)298 Value(const std::vector<Elt> &C) : Value(json::Array(C)) {} Value(json::Object && Properties)299 Value(json::Object &&Properties) : Type(T_Object) { 300 create<json::Object>(std::move(Properties)); 301 } 302 template <typename Elt> Value(const std::map<std::string,Elt> & C)303 Value(const std::map<std::string, Elt> &C) : Value(json::Object(C)) {} 304 // Strings: types with value semantics. Must be valid UTF-8. Value(std::string V)305 Value(std::string V) : Type(T_String) { 306 if (LLVM_UNLIKELY(!isUTF8(V))) { 307 assert(false && "Invalid UTF-8 in value used as JSON"); 308 V = fixUTF8(std::move(V)); 309 } 310 create<std::string>(std::move(V)); 311 } Value(const llvm::SmallVectorImpl<char> & V)312 Value(const llvm::SmallVectorImpl<char> &V) 313 : Value(std::string(V.begin(), V.end())){}; Value(const llvm::formatv_object_base & V)314 Value(const llvm::formatv_object_base &V) : Value(V.str()){}; 315 // Strings: types with reference semantics. Must be valid UTF-8. Value(StringRef V)316 Value(StringRef V) : Type(T_StringRef) { 317 create<llvm::StringRef>(V); 318 if (LLVM_UNLIKELY(!isUTF8(V))) { 319 assert(false && "Invalid UTF-8 in value used as JSON"); 320 *this = Value(fixUTF8(V)); 321 } 322 } Value(const char * V)323 Value(const char *V) : Value(StringRef(V)) {} Value(std::nullptr_t)324 Value(std::nullptr_t) : Type(T_Null) {} 325 // Boolean (disallow implicit conversions). 326 // (The last template parameter is a dummy to keep templates distinct.) 327 template < 328 typename T, 329 typename = typename std::enable_if<std::is_same<T, bool>::value>::type, 330 bool = false> Value(T B)331 Value(T B) : Type(T_Boolean) { 332 create<bool>(B); 333 } 334 // Integers (except boolean). Must be non-narrowing convertible to int64_t. 335 template < 336 typename T, 337 typename = typename std::enable_if<std::is_integral<T>::value>::type, 338 typename = typename std::enable_if<!std::is_same<T, bool>::value>::type> Value(T I)339 Value(T I) : Type(T_Integer) { 340 create<int64_t>(int64_t{I}); 341 } 342 // Floating point. Must be non-narrowing convertible to double. 343 template <typename T, 344 typename = 345 typename std::enable_if<std::is_floating_point<T>::value>::type, 346 double * = nullptr> Value(T D)347 Value(T D) : Type(T_Double) { 348 create<double>(double{D}); 349 } 350 // Serializable types: with a toJSON(const T&)->Value function, found by ADL. 351 template <typename T, 352 typename = typename std::enable_if<std::is_same< 353 Value, decltype(toJSON(*(const T *)nullptr))>::value>, 354 Value * = nullptr> Value(const T & V)355 Value(const T &V) : Value(toJSON(V)) {} 356 357 Value &operator=(const Value &M) { 358 destroy(); 359 copyFrom(M); 360 return *this; 361 } 362 Value &operator=(Value &&M) { 363 destroy(); 364 moveFrom(std::move(M)); 365 return *this; 366 } ~Value()367 ~Value() { destroy(); } 368 kind()369 Kind kind() const { 370 switch (Type) { 371 case T_Null: 372 return Null; 373 case T_Boolean: 374 return Boolean; 375 case T_Double: 376 case T_Integer: 377 return Number; 378 case T_String: 379 case T_StringRef: 380 return String; 381 case T_Object: 382 return Object; 383 case T_Array: 384 return Array; 385 } 386 llvm_unreachable("Unknown kind"); 387 } 388 389 // Typed accessors return None/nullptr if the Value is not of this type. getAsNull()390 llvm::Optional<std::nullptr_t> getAsNull() const { 391 if (LLVM_LIKELY(Type == T_Null)) 392 return nullptr; 393 return llvm::None; 394 } getAsBoolean()395 llvm::Optional<bool> getAsBoolean() const { 396 if (LLVM_LIKELY(Type == T_Boolean)) 397 return as<bool>(); 398 return llvm::None; 399 } getAsNumber()400 llvm::Optional<double> getAsNumber() const { 401 if (LLVM_LIKELY(Type == T_Double)) 402 return as<double>(); 403 if (LLVM_LIKELY(Type == T_Integer)) 404 return as<int64_t>(); 405 return llvm::None; 406 } 407 // Succeeds if the Value is a Number, and exactly representable as int64_t. getAsInteger()408 llvm::Optional<int64_t> getAsInteger() const { 409 if (LLVM_LIKELY(Type == T_Integer)) 410 return as<int64_t>(); 411 if (LLVM_LIKELY(Type == T_Double)) { 412 double D = as<double>(); 413 if (LLVM_LIKELY(std::modf(D, &D) == 0.0 && 414 D >= double(std::numeric_limits<int64_t>::min()) && 415 D <= double(std::numeric_limits<int64_t>::max()))) 416 return D; 417 } 418 return llvm::None; 419 } getAsString()420 llvm::Optional<llvm::StringRef> getAsString() const { 421 if (Type == T_String) 422 return llvm::StringRef(as<std::string>()); 423 if (LLVM_LIKELY(Type == T_StringRef)) 424 return as<llvm::StringRef>(); 425 return llvm::None; 426 } getAsObject()427 const json::Object *getAsObject() const { 428 return LLVM_LIKELY(Type == T_Object) ? &as<json::Object>() : nullptr; 429 } getAsObject()430 json::Object *getAsObject() { 431 return LLVM_LIKELY(Type == T_Object) ? &as<json::Object>() : nullptr; 432 } getAsArray()433 const json::Array *getAsArray() const { 434 return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr; 435 } getAsArray()436 json::Array *getAsArray() { 437 return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr; 438 } 439 440 /// Serializes this Value to JSON, writing it to the provided stream. 441 /// The formatting is compact (no extra whitespace) and deterministic. 442 /// For pretty-printing, use the formatv() format_provider below. 443 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &); 444 445 private: 446 void destroy(); 447 void copyFrom(const Value &M); 448 // We allow moving from *const* Values, by marking all members as mutable! 449 // This hack is needed to support initializer-list syntax efficiently. 450 // (std::initializer_list<T> is a container of const T). 451 void moveFrom(const Value &&M); 452 friend class Array; 453 friend class Object; 454 create(U &&...V)455 template <typename T, typename... U> void create(U &&... V) { 456 new (reinterpret_cast<T *>(Union.buffer)) T(std::forward<U>(V)...); 457 } as()458 template <typename T> T &as() const { 459 // Using this two-step static_cast via void * instead of reinterpret_cast 460 // silences a -Wstrict-aliasing false positive from GCC6 and earlier. 461 void *Storage = static_cast<void *>(Union.buffer); 462 return *static_cast<T *>(Storage); 463 } 464 465 template <typename Indenter> 466 void print(llvm::raw_ostream &, const Indenter &) const; 467 friend struct llvm::format_provider<llvm::json::Value>; 468 469 enum ValueType : char { 470 T_Null, 471 T_Boolean, 472 T_Double, 473 T_Integer, 474 T_StringRef, 475 T_String, 476 T_Object, 477 T_Array, 478 }; 479 // All members mutable, see moveFrom(). 480 mutable ValueType Type; 481 mutable llvm::AlignedCharArrayUnion<bool, double, int64_t, llvm::StringRef, 482 std::string, json::Array, json::Object> 483 Union; 484 friend bool operator==(const Value &, const Value &); 485 }; 486 487 bool operator==(const Value &, const Value &); 488 inline bool operator!=(const Value &L, const Value &R) { return !(L == R); } 489 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &); 490 491 /// ObjectKey is a used to capture keys in Object. Like Value but: 492 /// - only strings are allowed 493 /// - it's optimized for the string literal case (Owned == nullptr) 494 /// Like Value, strings must be UTF-8. See isUTF8 documentation for details. 495 class ObjectKey { 496 public: 497 ObjectKey(const char *S) : ObjectKey(StringRef(S)) {} 498 ObjectKey(std::string S) : Owned(new std::string(std::move(S))) { 499 if (LLVM_UNLIKELY(!isUTF8(*Owned))) { 500 assert(false && "Invalid UTF-8 in value used as JSON"); 501 *Owned = fixUTF8(std::move(*Owned)); 502 } 503 Data = *Owned; 504 } 505 ObjectKey(llvm::StringRef S) : Data(S) { 506 if (LLVM_UNLIKELY(!isUTF8(Data))) { 507 assert(false && "Invalid UTF-8 in value used as JSON"); 508 *this = ObjectKey(fixUTF8(S)); 509 } 510 } 511 ObjectKey(const llvm::SmallVectorImpl<char> &V) 512 : ObjectKey(std::string(V.begin(), V.end())) {} 513 ObjectKey(const llvm::formatv_object_base &V) : ObjectKey(V.str()) {} 514 515 ObjectKey(const ObjectKey &C) { *this = C; } 516 ObjectKey(ObjectKey &&C) : ObjectKey(static_cast<const ObjectKey &&>(C)) {} 517 ObjectKey &operator=(const ObjectKey &C) { 518 if (C.Owned) { 519 Owned.reset(new std::string(*C.Owned)); 520 Data = *Owned; 521 } else { 522 Data = C.Data; 523 } 524 return *this; 525 } 526 ObjectKey &operator=(ObjectKey &&) = default; 527 528 operator llvm::StringRef() const { return Data; } 529 std::string str() const { return Data.str(); } 530 531 private: 532 // FIXME: this is unneccesarily large (3 pointers). Pointer + length + owned 533 // could be 2 pointers at most. 534 std::unique_ptr<std::string> Owned; 535 llvm::StringRef Data; 536 }; 537 538 inline bool operator==(const ObjectKey &L, const ObjectKey &R) { 539 return llvm::StringRef(L) == llvm::StringRef(R); 540 } 541 inline bool operator!=(const ObjectKey &L, const ObjectKey &R) { 542 return !(L == R); 543 } 544 inline bool operator<(const ObjectKey &L, const ObjectKey &R) { 545 return StringRef(L) < StringRef(R); 546 } 547 548 struct Object::KV { 549 ObjectKey K; 550 Value V; 551 }; 552 553 inline Object::Object(std::initializer_list<KV> Properties) { 554 for (const auto &P : Properties) { 555 auto R = try_emplace(P.K, nullptr); 556 if (R.second) 557 R.first->getSecond().moveFrom(std::move(P.V)); 558 } 559 } 560 inline std::pair<Object::iterator, bool> Object::insert(KV E) { 561 return try_emplace(std::move(E.K), std::move(E.V)); 562 } 563 564 // Standard deserializers are provided for primitive types. 565 // See comments on Value. 566 inline bool fromJSON(const Value &E, std::string &Out) { 567 if (auto S = E.getAsString()) { 568 Out = *S; 569 return true; 570 } 571 return false; 572 } 573 inline bool fromJSON(const Value &E, int &Out) { 574 if (auto S = E.getAsInteger()) { 575 Out = *S; 576 return true; 577 } 578 return false; 579 } 580 inline bool fromJSON(const Value &E, int64_t &Out) { 581 if (auto S = E.getAsInteger()) { 582 Out = *S; 583 return true; 584 } 585 return false; 586 } 587 inline bool fromJSON(const Value &E, double &Out) { 588 if (auto S = E.getAsNumber()) { 589 Out = *S; 590 return true; 591 } 592 return false; 593 } 594 inline bool fromJSON(const Value &E, bool &Out) { 595 if (auto S = E.getAsBoolean()) { 596 Out = *S; 597 return true; 598 } 599 return false; 600 } 601 template <typename T> bool fromJSON(const Value &E, llvm::Optional<T> &Out) { 602 if (E.getAsNull()) { 603 Out = llvm::None; 604 return true; 605 } 606 T Result; 607 if (!fromJSON(E, Result)) 608 return false; 609 Out = std::move(Result); 610 return true; 611 } 612 template <typename T> bool fromJSON(const Value &E, std::vector<T> &Out) { 613 if (auto *A = E.getAsArray()) { 614 Out.clear(); 615 Out.resize(A->size()); 616 for (size_t I = 0; I < A->size(); ++I) 617 if (!fromJSON((*A)[I], Out[I])) 618 return false; 619 return true; 620 } 621 return false; 622 } 623 template <typename T> 624 bool fromJSON(const Value &E, std::map<std::string, T> &Out) { 625 if (auto *O = E.getAsObject()) { 626 Out.clear(); 627 for (const auto &KV : *O) 628 if (!fromJSON(KV.second, Out[llvm::StringRef(KV.first)])) 629 return false; 630 return true; 631 } 632 return false; 633 } 634 635 // Allow serialization of Optional<T> for supported T. 636 template <typename T> Value toJSON(const llvm::Optional<T> &Opt) { 637 return Opt ? Value(*Opt) : Value(nullptr); 638 } 639 640 /// Helper for mapping JSON objects onto protocol structs. 641 /// 642 /// Example: 643 /// \code 644 /// bool fromJSON(const Value &E, MyStruct &R) { 645 /// ObjectMapper O(E); 646 /// if (!O || !O.map("mandatory_field", R.MandatoryField)) 647 /// return false; 648 /// O.map("optional_field", R.OptionalField); 649 /// return true; 650 /// } 651 /// \endcode 652 class ObjectMapper { 653 public: 654 ObjectMapper(const Value &E) : O(E.getAsObject()) {} 655 656 /// True if the expression is an object. 657 /// Must be checked before calling map(). 658 operator bool() { return O; } 659 660 /// Maps a property to a field, if it exists. 661 template <typename T> bool map(StringRef Prop, T &Out) { 662 assert(*this && "Must check this is an object before calling map()"); 663 if (const Value *E = O->get(Prop)) 664 return fromJSON(*E, Out); 665 return false; 666 } 667 668 /// Maps a property to a field, if it exists. 669 /// (Optional requires special handling, because missing keys are OK). 670 template <typename T> bool map(StringRef Prop, llvm::Optional<T> &Out) { 671 assert(*this && "Must check this is an object before calling map()"); 672 if (const Value *E = O->get(Prop)) 673 return fromJSON(*E, Out); 674 Out = llvm::None; 675 return true; 676 } 677 678 private: 679 const Object *O; 680 }; 681 682 /// Parses the provided JSON source, or returns a ParseError. 683 /// The returned Value is self-contained and owns its strings (they do not refer 684 /// to the original source). 685 llvm::Expected<Value> parse(llvm::StringRef JSON); 686 687 class ParseError : public llvm::ErrorInfo<ParseError> { 688 const char *Msg; 689 unsigned Line, Column, Offset; 690 691 public: 692 static char ID; 693 ParseError(const char *Msg, unsigned Line, unsigned Column, unsigned Offset) 694 : Msg(Msg), Line(Line), Column(Column), Offset(Offset) {} 695 void log(llvm::raw_ostream &OS) const override { 696 OS << llvm::formatv("[{0}:{1}, byte={2}]: {3}", Line, Column, Offset, Msg); 697 } 698 std::error_code convertToErrorCode() const override { 699 return llvm::inconvertibleErrorCode(); 700 } 701 }; 702 } // namespace json 703 704 /// Allow printing json::Value with formatv(). 705 /// The default style is basic/compact formatting, like operator<<. 706 /// A format string like formatv("{0:2}", Value) pretty-prints with indent 2. 707 template <> struct format_provider<llvm::json::Value> { 708 static void format(const llvm::json::Value &, raw_ostream &, StringRef); 709 }; 710 } // namespace llvm 711 712 #endif 713