File indexing completed on 2026-05-10 08:44:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #ifndef LLVM_SUPPORT_JSON_H
0047 #define LLVM_SUPPORT_JSON_H
0048
0049 #include "llvm/ADT/DenseMap.h"
0050 #include "llvm/ADT/STLFunctionalExtras.h"
0051 #include "llvm/ADT/SmallVector.h"
0052 #include "llvm/ADT/StringRef.h"
0053 #include "llvm/Support/Compiler.h"
0054 #include "llvm/Support/Error.h"
0055 #include "llvm/Support/FormatVariadic.h"
0056 #include "llvm/Support/raw_ostream.h"
0057 #include <cmath>
0058 #include <map>
0059
0060 namespace llvm {
0061 namespace json {
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 template <typename T>
0079 constexpr bool is_uint_64_bit_v =
0080 std::is_integral_v<T> && std::is_unsigned_v<T> &&
0081 sizeof(T) == sizeof(uint64_t);
0082
0083
0084
0085 bool isUTF8(llvm::StringRef S, size_t *ErrOffset = nullptr);
0086
0087
0088
0089 std::string fixUTF8(llvm::StringRef S);
0090
0091 class Array;
0092 class ObjectKey;
0093 class Value;
0094 template <typename T> Value toJSON(const std::optional<T> &Opt);
0095
0096
0097
0098 class Object {
0099 using Storage = DenseMap<ObjectKey, Value, llvm::DenseMapInfo<StringRef>>;
0100 Storage M;
0101
0102 public:
0103 using key_type = ObjectKey;
0104 using mapped_type = Value;
0105 using value_type = Storage::value_type;
0106 using iterator = Storage::iterator;
0107 using const_iterator = Storage::const_iterator;
0108
0109 Object() = default;
0110
0111
0112 struct KV;
0113 explicit Object(std::initializer_list<KV> Properties);
0114
0115 iterator begin() { return M.begin(); }
0116 const_iterator begin() const { return M.begin(); }
0117 iterator end() { return M.end(); }
0118 const_iterator end() const { return M.end(); }
0119
0120 bool empty() const { return M.empty(); }
0121 size_t size() const { return M.size(); }
0122
0123 void clear() { M.clear(); }
0124 std::pair<iterator, bool> insert(KV E);
0125 template <typename... Ts>
0126 std::pair<iterator, bool> try_emplace(const ObjectKey &K, Ts &&... Args) {
0127 return M.try_emplace(K, std::forward<Ts>(Args)...);
0128 }
0129 template <typename... Ts>
0130 std::pair<iterator, bool> try_emplace(ObjectKey &&K, Ts &&... Args) {
0131 return M.try_emplace(std::move(K), std::forward<Ts>(Args)...);
0132 }
0133 bool erase(StringRef K);
0134 void erase(iterator I) { M.erase(I); }
0135
0136 iterator find(StringRef K) { return M.find_as(K); }
0137 const_iterator find(StringRef K) const { return M.find_as(K); }
0138
0139 Value &operator[](const ObjectKey &K);
0140 Value &operator[](ObjectKey &&K);
0141
0142 Value *get(StringRef K);
0143 const Value *get(StringRef K) const;
0144
0145
0146
0147 std::optional<std::nullptr_t> getNull(StringRef K) const;
0148 std::optional<bool> getBoolean(StringRef K) const;
0149 std::optional<double> getNumber(StringRef K) const;
0150 std::optional<int64_t> getInteger(StringRef K) const;
0151 std::optional<llvm::StringRef> getString(StringRef K) const;
0152 const json::Object *getObject(StringRef K) const;
0153 json::Object *getObject(StringRef K);
0154 const json::Array *getArray(StringRef K) const;
0155 json::Array *getArray(StringRef K);
0156 };
0157 bool operator==(const Object &LHS, const Object &RHS);
0158 inline bool operator!=(const Object &LHS, const Object &RHS) {
0159 return !(LHS == RHS);
0160 }
0161
0162
0163
0164 class Array {
0165 std::vector<Value> V;
0166
0167 public:
0168 using value_type = Value;
0169 using iterator = std::vector<Value>::iterator;
0170 using const_iterator = std::vector<Value>::const_iterator;
0171
0172 Array() = default;
0173 explicit Array(std::initializer_list<Value> Elements);
0174 template <typename Collection> explicit Array(const Collection &C) {
0175 for (const auto &V : C)
0176 emplace_back(V);
0177 }
0178
0179 Value &operator[](size_t I);
0180 const Value &operator[](size_t I) const;
0181 Value &front();
0182 const Value &front() const;
0183 Value &back();
0184 const Value &back() const;
0185 Value *data();
0186 const Value *data() const;
0187
0188 iterator begin();
0189 const_iterator begin() const;
0190 iterator end();
0191 const_iterator end() const;
0192
0193 bool empty() const;
0194 size_t size() const;
0195 void reserve(size_t S);
0196
0197 void clear();
0198 void push_back(const Value &E);
0199 void push_back(Value &&E);
0200 template <typename... Args> void emplace_back(Args &&...A);
0201 void pop_back();
0202 iterator insert(const_iterator P, const Value &E);
0203 iterator insert(const_iterator P, Value &&E);
0204 template <typename It> iterator insert(const_iterator P, It A, It Z);
0205 template <typename... Args> iterator emplace(const_iterator P, Args &&...A);
0206
0207 friend bool operator==(const Array &L, const Array &R);
0208 };
0209 inline bool operator!=(const Array &L, const Array &R) { return !(L == R); }
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288 class Value {
0289 public:
0290 enum Kind {
0291 Null,
0292 Boolean,
0293
0294
0295 Number,
0296 String,
0297 Array,
0298 Object,
0299 };
0300
0301
0302 Value(const Value &M) { copyFrom(M); }
0303 Value(Value &&M) { moveFrom(std::move(M)); }
0304 Value(std::initializer_list<Value> Elements);
0305 Value(json::Array &&Elements) : Type(T_Array) {
0306 create<json::Array>(std::move(Elements));
0307 }
0308 template <typename Elt>
0309 Value(const std::vector<Elt> &C) : Value(json::Array(C)) {}
0310 Value(json::Object &&Properties) : Type(T_Object) {
0311 create<json::Object>(std::move(Properties));
0312 }
0313 template <typename Elt>
0314 Value(const std::map<std::string, Elt> &C) : Value(json::Object(C)) {}
0315
0316 Value(std::string V) : Type(T_String) {
0317 if (LLVM_UNLIKELY(!isUTF8(V))) {
0318 assert(false && "Invalid UTF-8 in value used as JSON");
0319 V = fixUTF8(std::move(V));
0320 }
0321 create<std::string>(std::move(V));
0322 }
0323 Value(const llvm::SmallVectorImpl<char> &V)
0324 : Value(std::string(V.begin(), V.end())) {}
0325 Value(const llvm::formatv_object_base &V) : Value(V.str()) {}
0326
0327 Value(StringRef V) : Type(T_StringRef) {
0328 create<llvm::StringRef>(V);
0329 if (LLVM_UNLIKELY(!isUTF8(V))) {
0330 assert(false && "Invalid UTF-8 in value used as JSON");
0331 *this = Value(fixUTF8(V));
0332 }
0333 }
0334 Value(const char *V) : Value(StringRef(V)) {}
0335 Value(std::nullptr_t) : Type(T_Null) {}
0336
0337
0338 template <typename T, typename = std::enable_if_t<std::is_same_v<T, bool>>,
0339 bool = false>
0340 Value(T B) : Type(T_Boolean) {
0341 create<bool>(B);
0342 }
0343
0344
0345 template <typename T, typename = std::enable_if_t<is_uint_64_bit_v<T>>>
0346 Value(T V) : Type(T_UINT64) {
0347 create<uint64_t>(uint64_t{V});
0348 }
0349
0350
0351
0352 template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>,
0353 typename = std::enable_if_t<!std::is_same_v<T, bool>>,
0354 typename = std::enable_if_t<!is_uint_64_bit_v<T>>>
0355 Value(T I) : Type(T_Integer) {
0356 create<int64_t>(int64_t{I});
0357 }
0358
0359 template <typename T,
0360 typename = std::enable_if_t<std::is_floating_point_v<T>>,
0361 double * = nullptr>
0362 Value(T D) : Type(T_Double) {
0363 create<double>(double{D});
0364 }
0365
0366 template <typename T,
0367 typename = std::enable_if_t<
0368 std::is_same_v<Value, decltype(toJSON(*(const T *)nullptr))>>,
0369 Value * = nullptr>
0370 Value(const T &V) : Value(toJSON(V)) {}
0371
0372 Value &operator=(const Value &M) {
0373 destroy();
0374 copyFrom(M);
0375 return *this;
0376 }
0377 Value &operator=(Value &&M) {
0378 destroy();
0379 moveFrom(std::move(M));
0380 return *this;
0381 }
0382 ~Value() { destroy(); }
0383
0384 Kind kind() const {
0385 switch (Type) {
0386 case T_Null:
0387 return Null;
0388 case T_Boolean:
0389 return Boolean;
0390 case T_Double:
0391 case T_Integer:
0392 case T_UINT64:
0393 return Number;
0394 case T_String:
0395 case T_StringRef:
0396 return String;
0397 case T_Object:
0398 return Object;
0399 case T_Array:
0400 return Array;
0401 }
0402 llvm_unreachable("Unknown kind");
0403 }
0404
0405
0406
0407 std::optional<std::nullptr_t> getAsNull() const {
0408 if (LLVM_LIKELY(Type == T_Null))
0409 return nullptr;
0410 return std::nullopt;
0411 }
0412 std::optional<bool> getAsBoolean() const {
0413 if (LLVM_LIKELY(Type == T_Boolean))
0414 return as<bool>();
0415 return std::nullopt;
0416 }
0417 std::optional<double> getAsNumber() const {
0418 if (LLVM_LIKELY(Type == T_Double))
0419 return as<double>();
0420 if (LLVM_LIKELY(Type == T_Integer))
0421 return as<int64_t>();
0422 if (LLVM_LIKELY(Type == T_UINT64))
0423 return as<uint64_t>();
0424 return std::nullopt;
0425 }
0426
0427 std::optional<int64_t> getAsInteger() const {
0428 if (LLVM_LIKELY(Type == T_Integer))
0429 return as<int64_t>();
0430 if (LLVM_LIKELY(Type == T_UINT64)) {
0431 uint64_t U = as<uint64_t>();
0432 if (LLVM_LIKELY(U <= uint64_t(std::numeric_limits<int64_t>::max()))) {
0433 return U;
0434 }
0435 }
0436 if (LLVM_LIKELY(Type == T_Double)) {
0437 double D = as<double>();
0438 if (LLVM_LIKELY(std::modf(D, &D) == 0.0 &&
0439 D >= double(std::numeric_limits<int64_t>::min()) &&
0440 D <= double(std::numeric_limits<int64_t>::max())))
0441 return D;
0442 }
0443 return std::nullopt;
0444 }
0445 std::optional<uint64_t> getAsUINT64() const {
0446 if (Type == T_UINT64)
0447 return as<uint64_t>();
0448 else if (Type == T_Integer) {
0449 int64_t N = as<int64_t>();
0450 if (N >= 0)
0451 return as<uint64_t>();
0452 }
0453 return std::nullopt;
0454 }
0455 std::optional<llvm::StringRef> getAsString() const {
0456 if (Type == T_String)
0457 return llvm::StringRef(as<std::string>());
0458 if (LLVM_LIKELY(Type == T_StringRef))
0459 return as<llvm::StringRef>();
0460 return std::nullopt;
0461 }
0462 const json::Object *getAsObject() const {
0463 return LLVM_LIKELY(Type == T_Object) ? &as<json::Object>() : nullptr;
0464 }
0465 json::Object *getAsObject() {
0466 return LLVM_LIKELY(Type == T_Object) ? &as<json::Object>() : nullptr;
0467 }
0468 const json::Array *getAsArray() const {
0469 return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr;
0470 }
0471 json::Array *getAsArray() {
0472 return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr;
0473 }
0474
0475 private:
0476 void destroy();
0477 void copyFrom(const Value &M);
0478
0479
0480
0481 void moveFrom(const Value &&M);
0482 friend class Array;
0483 friend class Object;
0484
0485 template <typename T, typename... U> void create(U &&... V) {
0486 #if LLVM_ADDRESS_SANITIZER_BUILD
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496 __asan_unpoison_memory_region(&Union, sizeof(T));
0497 #endif
0498 new (reinterpret_cast<T *>(&Union)) T(std::forward<U>(V)...);
0499 }
0500 template <typename T> T &as() const {
0501
0502
0503 void *Storage = static_cast<void *>(&Union);
0504 return *static_cast<T *>(Storage);
0505 }
0506
0507 friend class OStream;
0508
0509 enum ValueType : char16_t {
0510 T_Null,
0511 T_Boolean,
0512 T_Double,
0513 T_Integer,
0514 T_UINT64,
0515 T_StringRef,
0516 T_String,
0517 T_Object,
0518 T_Array,
0519 };
0520
0521 mutable ValueType Type;
0522 mutable llvm::AlignedCharArrayUnion<bool, double, int64_t, uint64_t,
0523 llvm::StringRef, std::string, json::Array,
0524 json::Object>
0525 Union;
0526 friend bool operator==(const Value &, const Value &);
0527 };
0528
0529 bool operator==(const Value &, const Value &);
0530 inline bool operator!=(const Value &L, const Value &R) { return !(L == R); }
0531
0532
0533 inline Value &Array::operator[](size_t I) { return V[I]; }
0534 inline const Value &Array::operator[](size_t I) const { return V[I]; }
0535 inline Value &Array::front() { return V.front(); }
0536 inline const Value &Array::front() const { return V.front(); }
0537 inline Value &Array::back() { return V.back(); }
0538 inline const Value &Array::back() const { return V.back(); }
0539 inline Value *Array::data() { return V.data(); }
0540 inline const Value *Array::data() const { return V.data(); }
0541
0542 inline typename Array::iterator Array::begin() { return V.begin(); }
0543 inline typename Array::const_iterator Array::begin() const { return V.begin(); }
0544 inline typename Array::iterator Array::end() { return V.end(); }
0545 inline typename Array::const_iterator Array::end() const { return V.end(); }
0546
0547 inline bool Array::empty() const { return V.empty(); }
0548 inline size_t Array::size() const { return V.size(); }
0549 inline void Array::reserve(size_t S) { V.reserve(S); }
0550
0551 inline void Array::clear() { V.clear(); }
0552 inline void Array::push_back(const Value &E) { V.push_back(E); }
0553 inline void Array::push_back(Value &&E) { V.push_back(std::move(E)); }
0554 template <typename... Args> inline void Array::emplace_back(Args &&...A) {
0555 V.emplace_back(std::forward<Args>(A)...);
0556 }
0557 inline void Array::pop_back() { V.pop_back(); }
0558 inline typename Array::iterator Array::insert(const_iterator P, const Value &E) {
0559 return V.insert(P, E);
0560 }
0561 inline typename Array::iterator Array::insert(const_iterator P, Value &&E) {
0562 return V.insert(P, std::move(E));
0563 }
0564 template <typename It>
0565 inline typename Array::iterator Array::insert(const_iterator P, It A, It Z) {
0566 return V.insert(P, A, Z);
0567 }
0568 template <typename... Args>
0569 inline typename Array::iterator Array::emplace(const_iterator P, Args &&...A) {
0570 return V.emplace(P, std::forward<Args>(A)...);
0571 }
0572 inline bool operator==(const Array &L, const Array &R) { return L.V == R.V; }
0573
0574
0575
0576
0577
0578 class ObjectKey {
0579 public:
0580 ObjectKey(const char *S) : ObjectKey(StringRef(S)) {}
0581 ObjectKey(std::string S) : Owned(new std::string(std::move(S))) {
0582 if (LLVM_UNLIKELY(!isUTF8(*Owned))) {
0583 assert(false && "Invalid UTF-8 in value used as JSON");
0584 *Owned = fixUTF8(std::move(*Owned));
0585 }
0586 Data = *Owned;
0587 }
0588 ObjectKey(llvm::StringRef S) : Data(S) {
0589 if (LLVM_UNLIKELY(!isUTF8(Data))) {
0590 assert(false && "Invalid UTF-8 in value used as JSON");
0591 *this = ObjectKey(fixUTF8(S));
0592 }
0593 }
0594 ObjectKey(const llvm::SmallVectorImpl<char> &V)
0595 : ObjectKey(std::string(V.begin(), V.end())) {}
0596 ObjectKey(const llvm::formatv_object_base &V) : ObjectKey(V.str()) {}
0597
0598 ObjectKey(const ObjectKey &C) { *this = C; }
0599 ObjectKey(ObjectKey &&C) : ObjectKey(static_cast<const ObjectKey &&>(C)) {}
0600 ObjectKey &operator=(const ObjectKey &C) {
0601 if (C.Owned) {
0602 Owned.reset(new std::string(*C.Owned));
0603 Data = *Owned;
0604 } else {
0605 Data = C.Data;
0606 }
0607 return *this;
0608 }
0609 ObjectKey &operator=(ObjectKey &&) = default;
0610
0611 operator llvm::StringRef() const { return Data; }
0612 std::string str() const { return Data.str(); }
0613
0614 private:
0615
0616
0617 std::unique_ptr<std::string> Owned;
0618 llvm::StringRef Data;
0619 };
0620
0621 inline bool operator==(const ObjectKey &L, const ObjectKey &R) {
0622 return llvm::StringRef(L) == llvm::StringRef(R);
0623 }
0624 inline bool operator!=(const ObjectKey &L, const ObjectKey &R) {
0625 return !(L == R);
0626 }
0627 inline bool operator<(const ObjectKey &L, const ObjectKey &R) {
0628 return StringRef(L) < StringRef(R);
0629 }
0630
0631 struct Object::KV {
0632 ObjectKey K;
0633 Value V;
0634 };
0635
0636 inline Object::Object(std::initializer_list<KV> Properties) {
0637 for (const auto &P : Properties) {
0638 auto R = try_emplace(P.K, nullptr);
0639 if (R.second)
0640 R.first->getSecond().moveFrom(std::move(P.V));
0641 }
0642 }
0643 inline std::pair<Object::iterator, bool> Object::insert(KV E) {
0644 return try_emplace(std::move(E.K), std::move(E.V));
0645 }
0646 inline bool Object::erase(StringRef K) {
0647 return M.erase(ObjectKey(K));
0648 }
0649
0650 std::vector<const Object::value_type *> sortedElements(const Object &O);
0651
0652
0653
0654
0655 class Path {
0656 public:
0657 class Root;
0658
0659
0660
0661
0662 void report(llvm::StringLiteral Message);
0663
0664
0665 Path(Root &R) : Parent(nullptr), Seg(&R) {}
0666
0667 Path index(unsigned Index) const { return Path(this, Segment(Index)); }
0668
0669 Path field(StringRef Field) const { return Path(this, Segment(Field)); }
0670
0671 private:
0672
0673
0674 class Segment {
0675 uintptr_t Pointer;
0676 unsigned Offset;
0677
0678 public:
0679 Segment() = default;
0680 Segment(Root *R) : Pointer(reinterpret_cast<uintptr_t>(R)) {}
0681 Segment(llvm::StringRef Field)
0682 : Pointer(reinterpret_cast<uintptr_t>(Field.data())),
0683 Offset(static_cast<unsigned>(Field.size())) {}
0684 Segment(unsigned Index) : Pointer(0), Offset(Index) {}
0685
0686 bool isField() const { return Pointer != 0; }
0687 StringRef field() const {
0688 return StringRef(reinterpret_cast<const char *>(Pointer), Offset);
0689 }
0690 unsigned index() const { return Offset; }
0691 Root *root() const { return reinterpret_cast<Root *>(Pointer); }
0692 };
0693
0694 const Path *Parent;
0695 Segment Seg;
0696
0697 Path(const Path *Parent, Segment S) : Parent(Parent), Seg(S) {}
0698 };
0699
0700
0701
0702 class Path::Root {
0703 llvm::StringRef Name;
0704 llvm::StringLiteral ErrorMessage;
0705 std::vector<Path::Segment> ErrorPath;
0706
0707 friend void Path::report(llvm::StringLiteral Message);
0708
0709 public:
0710 Root(llvm::StringRef Name = "") : Name(Name), ErrorMessage("") {}
0711
0712 Root(Root &&) = delete;
0713 Root &operator=(Root &&) = delete;
0714 Root(const Root &) = delete;
0715 Root &operator=(const Root &) = delete;
0716
0717
0718 Error getError() const;
0719
0720
0721
0722
0723
0724
0725
0726 void printErrorContext(const Value &, llvm::raw_ostream &) const;
0727 };
0728
0729
0730
0731 inline bool fromJSON(const Value &E, std::string &Out, Path P) {
0732 if (auto S = E.getAsString()) {
0733 Out = std::string(*S);
0734 return true;
0735 }
0736 P.report("expected string");
0737 return false;
0738 }
0739 inline bool fromJSON(const Value &E, int &Out, Path P) {
0740 if (auto S = E.getAsInteger()) {
0741 Out = *S;
0742 return true;
0743 }
0744 P.report("expected integer");
0745 return false;
0746 }
0747 inline bool fromJSON(const Value &E, int64_t &Out, Path P) {
0748 if (auto S = E.getAsInteger()) {
0749 Out = *S;
0750 return true;
0751 }
0752 P.report("expected integer");
0753 return false;
0754 }
0755 inline bool fromJSON(const Value &E, double &Out, Path P) {
0756 if (auto S = E.getAsNumber()) {
0757 Out = *S;
0758 return true;
0759 }
0760 P.report("expected number");
0761 return false;
0762 }
0763 inline bool fromJSON(const Value &E, bool &Out, Path P) {
0764 if (auto S = E.getAsBoolean()) {
0765 Out = *S;
0766 return true;
0767 }
0768 P.report("expected boolean");
0769 return false;
0770 }
0771 inline bool fromJSON(const Value &E, uint64_t &Out, Path P) {
0772 if (auto S = E.getAsUINT64()) {
0773 Out = *S;
0774 return true;
0775 }
0776 P.report("expected uint64_t");
0777 return false;
0778 }
0779 inline bool fromJSON(const Value &E, std::nullptr_t &Out, Path P) {
0780 if (auto S = E.getAsNull()) {
0781 Out = *S;
0782 return true;
0783 }
0784 P.report("expected null");
0785 return false;
0786 }
0787 template <typename T>
0788 bool fromJSON(const Value &E, std::optional<T> &Out, Path P) {
0789 if (E.getAsNull()) {
0790 Out = std::nullopt;
0791 return true;
0792 }
0793 T Result = {};
0794 if (!fromJSON(E, Result, P))
0795 return false;
0796 Out = std::move(Result);
0797 return true;
0798 }
0799 template <typename T>
0800 bool fromJSON(const Value &E, std::vector<T> &Out, Path P) {
0801 if (auto *A = E.getAsArray()) {
0802 Out.clear();
0803 Out.resize(A->size());
0804 for (size_t I = 0; I < A->size(); ++I)
0805 if (!fromJSON((*A)[I], Out[I], P.index(I)))
0806 return false;
0807 return true;
0808 }
0809 P.report("expected array");
0810 return false;
0811 }
0812 template <typename T>
0813 bool fromJSON(const Value &E, std::map<std::string, T> &Out, Path P) {
0814 if (auto *O = E.getAsObject()) {
0815 Out.clear();
0816 for (const auto &KV : *O)
0817 if (!fromJSON(KV.second, Out[std::string(llvm::StringRef(KV.first))],
0818 P.field(KV.first)))
0819 return false;
0820 return true;
0821 }
0822 P.report("expected object");
0823 return false;
0824 }
0825
0826
0827 template <typename T> Value toJSON(const std::optional<T> &Opt) {
0828 return Opt ? Value(*Opt) : Value(nullptr);
0829 }
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842 class ObjectMapper {
0843 public:
0844
0845 ObjectMapper(const Value &E, Path P) : O(E.getAsObject()), P(P) {
0846 if (!O)
0847 P.report("expected object");
0848 }
0849
0850
0851
0852 operator bool() const { return O; }
0853
0854
0855
0856 template <typename T> bool map(StringLiteral Prop, T &Out) {
0857 assert(*this && "Must check this is an object before calling map()");
0858 if (const Value *E = O->get(Prop))
0859 return fromJSON(*E, Out, P.field(Prop));
0860 P.field(Prop).report("missing value");
0861 return false;
0862 }
0863
0864
0865
0866
0867 template <typename T> bool map(StringLiteral Prop, std::optional<T> &Out) {
0868 assert(*this && "Must check this is an object before calling map()");
0869 if (const Value *E = O->get(Prop))
0870 return fromJSON(*E, Out, P.field(Prop));
0871 Out = std::nullopt;
0872 return true;
0873 }
0874
0875
0876
0877
0878 template <typename T> bool mapOptional(StringLiteral Prop, T &Out) {
0879 assert(*this && "Must check this is an object before calling map()");
0880 if (const Value *E = O->get(Prop))
0881 return fromJSON(*E, Out, P.field(Prop));
0882 return true;
0883 }
0884
0885 private:
0886 const Object *O;
0887 Path P;
0888 };
0889
0890
0891
0892
0893 llvm::Expected<Value> parse(llvm::StringRef JSON);
0894
0895 class ParseError : public llvm::ErrorInfo<ParseError> {
0896 const char *Msg;
0897 unsigned Line, Column, Offset;
0898
0899 public:
0900 static char ID;
0901 ParseError(const char *Msg, unsigned Line, unsigned Column, unsigned Offset)
0902 : Msg(Msg), Line(Line), Column(Column), Offset(Offset) {}
0903 void log(llvm::raw_ostream &OS) const override {
0904 OS << llvm::formatv("[{0}:{1}, byte={2}]: {3}", Line, Column, Offset, Msg);
0905 }
0906 std::error_code convertToErrorCode() const override {
0907 return llvm::inconvertibleErrorCode();
0908 }
0909 };
0910
0911
0912
0913 template <typename T>
0914 Expected<T> parse(const llvm::StringRef &JSON, const char *RootName = "") {
0915 auto V = parse(JSON);
0916 if (!V)
0917 return V.takeError();
0918 Path::Root R(RootName);
0919 T Result;
0920 if (fromJSON(*V, Result, R))
0921 return std::move(Result);
0922 return R.getError();
0923 }
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979 class OStream {
0980 public:
0981 using Block = llvm::function_ref<void()>;
0982
0983 explicit OStream(llvm::raw_ostream &OS, unsigned IndentSize = 0)
0984 : OS(OS), IndentSize(IndentSize) {
0985 Stack.emplace_back();
0986 }
0987 ~OStream() {
0988 assert(Stack.size() == 1 && "Unmatched begin()/end()");
0989 assert(Stack.back().Ctx == Singleton);
0990 assert(Stack.back().HasValue && "Did not write top-level value");
0991 }
0992
0993
0994 void flush() { OS.flush(); }
0995
0996
0997
0998
0999
1000
1001 void value(const Value &V);
1002
1003 void array(Block Contents) {
1004 arrayBegin();
1005 Contents();
1006 arrayEnd();
1007 }
1008
1009 void object(Block Contents) {
1010 objectBegin();
1011 Contents();
1012 objectEnd();
1013 }
1014
1015
1016
1017 void rawValue(llvm::function_ref<void(raw_ostream &)> Contents) {
1018 rawValueBegin();
1019 Contents(OS);
1020 rawValueEnd();
1021 }
1022 void rawValue(llvm::StringRef Contents) {
1023 rawValue([&](raw_ostream &OS) { OS << Contents; });
1024 }
1025
1026
1027
1028 void comment(llvm::StringRef);
1029
1030
1031
1032
1033
1034 void attribute(llvm::StringRef Key, const Value& Contents) {
1035 attributeImpl(Key, [&] { value(Contents); });
1036 }
1037
1038 void attributeArray(llvm::StringRef Key, Block Contents) {
1039 attributeImpl(Key, [&] { array(Contents); });
1040 }
1041
1042 void attributeObject(llvm::StringRef Key, Block Contents) {
1043 attributeImpl(Key, [&] { object(Contents); });
1044 }
1045
1046
1047
1048
1049 void arrayBegin();
1050 void arrayEnd();
1051 void objectBegin();
1052 void objectEnd();
1053 void attributeBegin(llvm::StringRef Key);
1054 void attributeEnd();
1055 raw_ostream &rawValueBegin();
1056 void rawValueEnd();
1057
1058 private:
1059 void attributeImpl(llvm::StringRef Key, Block Contents) {
1060 attributeBegin(Key);
1061 Contents();
1062 attributeEnd();
1063 }
1064
1065 void valueBegin();
1066 void flushComment();
1067 void newline();
1068
1069 enum Context {
1070 Singleton,
1071 Array,
1072 Object,
1073 RawValue,
1074 };
1075 struct State {
1076 Context Ctx = Singleton;
1077 bool HasValue = false;
1078 };
1079 llvm::SmallVector<State, 16> Stack;
1080 llvm::StringRef PendingComment;
1081 llvm::raw_ostream &OS;
1082 unsigned IndentSize;
1083 unsigned Indent = 0;
1084 };
1085
1086
1087
1088
1089 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Value &V) {
1090 OStream(OS).value(V);
1091 return OS;
1092 }
1093 }
1094
1095
1096
1097
1098 template <> struct format_provider<llvm::json::Value> {
1099 static void format(const llvm::json::Value &, raw_ostream &, StringRef);
1100 };
1101 }
1102
1103 #endif