File indexing completed on 2026-05-10 08:42:58
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLDB_UTILITY_STRUCTUREDDATA_H
0010 #define LLDB_UTILITY_STRUCTUREDDATA_H
0011
0012 #include "llvm/ADT/StringMap.h"
0013 #include "llvm/ADT/StringRef.h"
0014 #include "llvm/Support/JSON.h"
0015
0016 #include "lldb/Utility/FileSpec.h"
0017 #include "lldb/Utility/Stream.h"
0018 #include "lldb/lldb-enumerations.h"
0019
0020 #include <cassert>
0021 #include <cstddef>
0022 #include <cstdint>
0023 #include <functional>
0024 #include <map>
0025 #include <memory>
0026 #include <optional>
0027 #include <string>
0028 #include <type_traits>
0029 #include <utility>
0030 #include <variant>
0031 #include <vector>
0032
0033 namespace lldb_private {
0034 class Status;
0035 }
0036
0037 namespace lldb_private {
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 class StructuredData {
0053 template <typename N> class Integer;
0054
0055 public:
0056 class Object;
0057 class Array;
0058 using UnsignedInteger = Integer<uint64_t>;
0059 using SignedInteger = Integer<int64_t>;
0060 class Float;
0061 class Boolean;
0062 class String;
0063 class Dictionary;
0064 class Generic;
0065
0066 typedef std::shared_ptr<Object> ObjectSP;
0067 typedef std::shared_ptr<Array> ArraySP;
0068 typedef std::shared_ptr<UnsignedInteger> UnsignedIntegerSP;
0069 typedef std::shared_ptr<SignedInteger> SignedIntegerSP;
0070 typedef std::shared_ptr<Float> FloatSP;
0071 typedef std::shared_ptr<Boolean> BooleanSP;
0072 typedef std::shared_ptr<String> StringSP;
0073 typedef std::shared_ptr<Dictionary> DictionarySP;
0074 typedef std::shared_ptr<Generic> GenericSP;
0075
0076 typedef std::variant<UnsignedIntegerSP, SignedIntegerSP> IntegerSP;
0077
0078 class Object : public std::enable_shared_from_this<Object> {
0079 public:
0080 Object(lldb::StructuredDataType t = lldb::eStructuredDataTypeInvalid)
0081 : m_type(t) {}
0082
0083 virtual ~Object() = default;
0084
0085 virtual bool IsValid() const { return true; }
0086
0087 virtual void Clear() { m_type = lldb::eStructuredDataTypeInvalid; }
0088
0089 lldb::StructuredDataType GetType() const { return m_type; }
0090
0091 void SetType(lldb::StructuredDataType t) { m_type = t; }
0092
0093 Array *GetAsArray() {
0094 return ((m_type == lldb::eStructuredDataTypeArray)
0095 ? static_cast<Array *>(this)
0096 : nullptr);
0097 }
0098
0099 Dictionary *GetAsDictionary() {
0100 return ((m_type == lldb::eStructuredDataTypeDictionary)
0101 ? static_cast<Dictionary *>(this)
0102 : nullptr);
0103 }
0104
0105 UnsignedInteger *GetAsUnsignedInteger() {
0106
0107
0108 return ((m_type == lldb::eStructuredDataTypeInteger ||
0109 m_type == lldb::eStructuredDataTypeUnsignedInteger)
0110 ? static_cast<UnsignedInteger *>(this)
0111 : nullptr);
0112 }
0113
0114 SignedInteger *GetAsSignedInteger() {
0115 return ((m_type == lldb::eStructuredDataTypeSignedInteger)
0116 ? static_cast<SignedInteger *>(this)
0117 : nullptr);
0118 }
0119
0120 uint64_t GetUnsignedIntegerValue(uint64_t fail_value = 0) {
0121 UnsignedInteger *integer = GetAsUnsignedInteger();
0122 return ((integer != nullptr) ? integer->GetValue() : fail_value);
0123 }
0124
0125 int64_t GetSignedIntegerValue(int64_t fail_value = 0) {
0126 SignedInteger *integer = GetAsSignedInteger();
0127 return ((integer != nullptr) ? integer->GetValue() : fail_value);
0128 }
0129
0130 Float *GetAsFloat() {
0131 return ((m_type == lldb::eStructuredDataTypeFloat)
0132 ? static_cast<Float *>(this)
0133 : nullptr);
0134 }
0135
0136 double GetFloatValue(double fail_value = 0.0) {
0137 Float *f = GetAsFloat();
0138 return ((f != nullptr) ? f->GetValue() : fail_value);
0139 }
0140
0141 Boolean *GetAsBoolean() {
0142 return ((m_type == lldb::eStructuredDataTypeBoolean)
0143 ? static_cast<Boolean *>(this)
0144 : nullptr);
0145 }
0146
0147 bool GetBooleanValue(bool fail_value = false) {
0148 Boolean *b = GetAsBoolean();
0149 return ((b != nullptr) ? b->GetValue() : fail_value);
0150 }
0151
0152 String *GetAsString() {
0153 return ((m_type == lldb::eStructuredDataTypeString)
0154 ? static_cast<String *>(this)
0155 : nullptr);
0156 }
0157
0158 llvm::StringRef GetStringValue(const char *fail_value = nullptr) {
0159 String *s = GetAsString();
0160 if (s)
0161 return s->GetValue();
0162
0163 return fail_value;
0164 }
0165
0166 Generic *GetAsGeneric() {
0167 return ((m_type == lldb::eStructuredDataTypeGeneric)
0168 ? static_cast<Generic *>(this)
0169 : nullptr);
0170 }
0171
0172 ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);
0173
0174 void DumpToStdout(bool pretty_print = true) const;
0175
0176 virtual void Serialize(llvm::json::OStream &s) const = 0;
0177
0178 void Dump(lldb_private::Stream &s, bool pretty_print = true) const {
0179 llvm::json::OStream jso(s.AsRawOstream(), pretty_print ? 2 : 0);
0180 Serialize(jso);
0181 }
0182
0183 virtual void GetDescription(lldb_private::Stream &s) const {
0184 s.IndentMore();
0185 Dump(s, false);
0186 s.IndentLess();
0187 }
0188
0189 private:
0190 lldb::StructuredDataType m_type;
0191 };
0192
0193 class Array : public Object {
0194 public:
0195 Array() : Object(lldb::eStructuredDataTypeArray) {}
0196
0197 ~Array() override = default;
0198
0199 bool
0200 ForEach(std::function<bool(Object *object)> const &foreach_callback) const {
0201 for (const auto &object_sp : m_items) {
0202 if (!foreach_callback(object_sp.get()))
0203 return false;
0204 }
0205 return true;
0206 }
0207
0208 size_t GetSize() const { return m_items.size(); }
0209
0210 ObjectSP operator[](size_t idx) {
0211 if (idx < m_items.size())
0212 return m_items[idx];
0213 return ObjectSP();
0214 }
0215
0216 ObjectSP GetItemAtIndex(size_t idx) const {
0217 assert(idx < GetSize());
0218 if (idx < m_items.size())
0219 return m_items[idx];
0220 return ObjectSP();
0221 }
0222
0223 template <class IntType>
0224 std::optional<IntType> GetItemAtIndexAsInteger(size_t idx) const {
0225 if (auto item_sp = GetItemAtIndex(idx)) {
0226 if constexpr (std::numeric_limits<IntType>::is_signed) {
0227 if (auto *signed_value = item_sp->GetAsSignedInteger())
0228 return static_cast<IntType>(signed_value->GetValue());
0229 } else {
0230 if (auto *unsigned_value = item_sp->GetAsUnsignedInteger())
0231 return static_cast<IntType>(unsigned_value->GetValue());
0232 }
0233 }
0234 return {};
0235 }
0236
0237 std::optional<llvm::StringRef> GetItemAtIndexAsString(size_t idx) const {
0238 if (auto item_sp = GetItemAtIndex(idx)) {
0239 if (auto *string_value = item_sp->GetAsString())
0240 return string_value->GetValue();
0241 }
0242 return {};
0243 }
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 std::optional<Dictionary *> GetItemAtIndexAsDictionary(size_t idx) const {
0258 if (auto item_sp = GetItemAtIndex(idx)) {
0259 if (auto *dict = item_sp->GetAsDictionary())
0260 return dict;
0261 }
0262 return {};
0263 }
0264
0265 void Push(const ObjectSP &item) { m_items.push_back(item); }
0266
0267 void AddItem(const ObjectSP &item) { m_items.push_back(item); }
0268
0269 template <typename T> void AddIntegerItem(T value) {
0270 static_assert(std::is_integral<T>::value ||
0271 std::is_floating_point<T>::value,
0272 "value type should be integral");
0273 if constexpr (std::numeric_limits<T>::is_signed)
0274 AddItem(std::make_shared<SignedInteger>(value));
0275 else
0276 AddItem(std::make_shared<UnsignedInteger>(value));
0277 }
0278
0279 void AddFloatItem(double value) { AddItem(std::make_shared<Float>(value)); }
0280
0281 void AddStringItem(llvm::StringRef value) {
0282 AddItem(std::make_shared<String>(std::move(value)));
0283 }
0284
0285 void AddBooleanItem(bool value) {
0286 AddItem(std::make_shared<Boolean>(value));
0287 }
0288
0289 void Serialize(llvm::json::OStream &s) const override;
0290
0291 void GetDescription(lldb_private::Stream &s) const override;
0292
0293 protected:
0294 typedef std::vector<ObjectSP> collection;
0295 collection m_items;
0296 };
0297
0298 private:
0299 template <typename N> class Integer : public Object {
0300 static_assert(std::is_integral<N>::value, "N must be an integral type");
0301
0302 public:
0303 Integer(N i = 0)
0304 : Object(std::numeric_limits<N>::is_signed
0305 ? lldb::eStructuredDataTypeSignedInteger
0306 : lldb::eStructuredDataTypeUnsignedInteger),
0307 m_value(i) {}
0308 ~Integer() override = default;
0309
0310 void SetValue(N value) { m_value = value; }
0311
0312 N GetValue() { return m_value; }
0313
0314 void Serialize(llvm::json::OStream &s) const override {
0315 s.value(static_cast<N>(m_value));
0316 }
0317
0318 void GetDescription(lldb_private::Stream &s) const override {
0319 s.Printf(std::numeric_limits<N>::is_signed ? "%" PRId64 : "%" PRIu64,
0320 static_cast<N>(m_value));
0321 }
0322
0323 protected:
0324 N m_value;
0325 };
0326
0327 public:
0328 class Float : public Object {
0329 public:
0330 Float(double d = 0.0)
0331 : Object(lldb::eStructuredDataTypeFloat), m_value(d) {}
0332
0333 ~Float() override = default;
0334
0335 void SetValue(double value) { m_value = value; }
0336
0337 double GetValue() { return m_value; }
0338
0339 void Serialize(llvm::json::OStream &s) const override;
0340
0341 void GetDescription(lldb_private::Stream &s) const override;
0342
0343 protected:
0344 double m_value;
0345 };
0346
0347 class Boolean : public Object {
0348 public:
0349 Boolean(bool b = false)
0350 : Object(lldb::eStructuredDataTypeBoolean), m_value(b) {}
0351
0352 ~Boolean() override = default;
0353
0354 void SetValue(bool value) { m_value = value; }
0355
0356 bool GetValue() { return m_value; }
0357
0358 void Serialize(llvm::json::OStream &s) const override;
0359
0360 void GetDescription(lldb_private::Stream &s) const override;
0361
0362 protected:
0363 bool m_value;
0364 };
0365
0366 class String : public Object {
0367 public:
0368 String() : Object(lldb::eStructuredDataTypeString) {}
0369 explicit String(llvm::StringRef S)
0370 : Object(lldb::eStructuredDataTypeString), m_value(S) {}
0371
0372 void SetValue(llvm::StringRef S) { m_value = std::string(S); }
0373
0374 llvm::StringRef GetValue() { return m_value; }
0375
0376 void Serialize(llvm::json::OStream &s) const override;
0377
0378 void GetDescription(lldb_private::Stream &s) const override;
0379
0380 protected:
0381 std::string m_value;
0382 };
0383
0384 class Dictionary : public Object {
0385 public:
0386 Dictionary() : Object(lldb::eStructuredDataTypeDictionary) {}
0387
0388 Dictionary(ObjectSP obj_sp) : Object(lldb::eStructuredDataTypeDictionary) {
0389 if (!obj_sp || obj_sp->GetType() != lldb::eStructuredDataTypeDictionary) {
0390 SetType(lldb::eStructuredDataTypeInvalid);
0391 return;
0392 }
0393
0394 Dictionary *dict = obj_sp->GetAsDictionary();
0395 m_dict = dict->m_dict;
0396 }
0397
0398 ~Dictionary() override = default;
0399
0400 size_t GetSize() const { return m_dict.size(); }
0401
0402 void ForEach(std::function<bool(llvm::StringRef key, Object *object)> const
0403 &callback) const {
0404 for (const auto &pair : m_dict) {
0405 if (!callback(pair.first(), pair.second.get()))
0406 break;
0407 }
0408 }
0409
0410 ArraySP GetKeys() const {
0411 auto array_sp = std::make_shared<Array>();
0412 for (auto iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
0413 auto key_object_sp = std::make_shared<String>(iter->first());
0414 array_sp->Push(key_object_sp);
0415 }
0416 return array_sp;
0417 }
0418
0419 ObjectSP GetValueForKey(llvm::StringRef key) const {
0420 return m_dict.lookup(key);
0421 }
0422
0423 bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const {
0424 bool success = false;
0425 ObjectSP value_sp = GetValueForKey(key);
0426 if (value_sp.get()) {
0427 Boolean *result_ptr = value_sp->GetAsBoolean();
0428 if (result_ptr) {
0429 result = result_ptr->GetValue();
0430 success = true;
0431 }
0432 }
0433 return success;
0434 }
0435
0436 template <class IntType>
0437 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
0438 ObjectSP value_sp = GetValueForKey(key);
0439 if (value_sp) {
0440 if constexpr (std::numeric_limits<IntType>::is_signed) {
0441 if (auto signed_value = value_sp->GetAsSignedInteger()) {
0442 result = static_cast<IntType>(signed_value->GetValue());
0443 return true;
0444 }
0445 } else {
0446 if (auto unsigned_value = value_sp->GetAsUnsignedInteger()) {
0447 result = static_cast<IntType>(unsigned_value->GetValue());
0448 return true;
0449 }
0450 }
0451 }
0452 return false;
0453 }
0454
0455 template <class IntType>
0456 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result,
0457 IntType default_val) const {
0458 bool success = GetValueForKeyAsInteger<IntType>(key, result);
0459 if (!success)
0460 result = default_val;
0461 return success;
0462 }
0463
0464 bool GetValueForKeyAsString(llvm::StringRef key,
0465 llvm::StringRef &result) const {
0466 ObjectSP value_sp = GetValueForKey(key);
0467 if (value_sp.get()) {
0468 if (auto string_value = value_sp->GetAsString()) {
0469 result = string_value->GetValue();
0470 return true;
0471 }
0472 }
0473 return false;
0474 }
0475
0476 bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result,
0477 const char *default_val) const {
0478 bool success = GetValueForKeyAsString(key, result);
0479 if (!success) {
0480 if (default_val)
0481 result = default_val;
0482 else
0483 result = llvm::StringRef();
0484 }
0485 return success;
0486 }
0487
0488 bool GetValueForKeyAsDictionary(llvm::StringRef key,
0489 Dictionary *&result) const {
0490 result = nullptr;
0491 ObjectSP value_sp = GetValueForKey(key);
0492 if (value_sp.get()) {
0493 result = value_sp->GetAsDictionary();
0494 return (result != nullptr);
0495 }
0496 return false;
0497 }
0498
0499 bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const {
0500 result = nullptr;
0501 ObjectSP value_sp = GetValueForKey(key);
0502 if (value_sp.get()) {
0503 result = value_sp->GetAsArray();
0504 return (result != nullptr);
0505 }
0506 return false;
0507 }
0508
0509 bool HasKey(llvm::StringRef key) const { return m_dict.contains(key); }
0510
0511 void AddItem(llvm::StringRef key, ObjectSP value_sp) {
0512 m_dict.insert_or_assign(key, std::move(value_sp));
0513 }
0514
0515 template <typename T> void AddIntegerItem(llvm::StringRef key, T value) {
0516 static_assert(std::is_integral<T>::value ||
0517 std::is_floating_point<T>::value,
0518 "value type should be integral");
0519 if constexpr (std::numeric_limits<T>::is_signed)
0520 AddItem(key, std::make_shared<SignedInteger>(value));
0521 else
0522 AddItem(key, std::make_shared<UnsignedInteger>(value));
0523 }
0524
0525 void AddFloatItem(llvm::StringRef key, double value) {
0526 AddItem(key, std::make_shared<Float>(value));
0527 }
0528
0529 void AddStringItem(llvm::StringRef key, llvm::StringRef value) {
0530 AddItem(key, std::make_shared<String>(std::move(value)));
0531 }
0532
0533 void AddBooleanItem(llvm::StringRef key, bool value) {
0534 AddItem(key, std::make_shared<Boolean>(value));
0535 }
0536
0537 void Serialize(llvm::json::OStream &s) const override;
0538
0539 void GetDescription(lldb_private::Stream &s) const override;
0540
0541 protected:
0542 llvm::StringMap<ObjectSP> m_dict;
0543 };
0544
0545 class Null : public Object {
0546 public:
0547 Null() : Object(lldb::eStructuredDataTypeNull) {}
0548
0549 ~Null() override = default;
0550
0551 bool IsValid() const override { return false; }
0552
0553 void Serialize(llvm::json::OStream &s) const override;
0554
0555 void GetDescription(lldb_private::Stream &s) const override;
0556 };
0557
0558 class Generic : public Object {
0559 public:
0560 explicit Generic(void *object = nullptr)
0561 : Object(lldb::eStructuredDataTypeGeneric), m_object(object) {}
0562
0563 void SetValue(void *value) { m_object = value; }
0564
0565 void *GetValue() const { return m_object; }
0566
0567 bool IsValid() const override { return m_object != nullptr; }
0568
0569 void Serialize(llvm::json::OStream &s) const override;
0570
0571 void GetDescription(lldb_private::Stream &s) const override;
0572
0573 private:
0574 void *m_object;
0575 };
0576
0577 static ObjectSP ParseJSON(llvm::StringRef json_text);
0578 static ObjectSP ParseJSONFromFile(const FileSpec &file, Status &error);
0579 static bool IsRecordType(const ObjectSP object_sp);
0580 };
0581
0582 }
0583
0584 #endif