Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:58

0001 //===-- StructuredData.h ----------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
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 /// \class StructuredData StructuredData.h "lldb/Utility/StructuredData.h"
0040 /// A class which can hold structured data
0041 ///
0042 /// The StructuredData class is designed to hold the data from a JSON or plist
0043 /// style file -- a serialized data structure with dictionaries (maps,
0044 /// hashes), arrays, and concrete values like integers, floating point
0045 /// numbers, strings, booleans.
0046 ///
0047 /// StructuredData does not presuppose any knowledge of the schema for the
0048 /// data it is holding; it can parse JSON data, for instance, and other parts
0049 /// of lldb can iterate through the parsed data set to find keys and values
0050 /// that may be present.
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       // NOTE: For backward compatibility, eStructuredDataTypeInteger is
0107       // the same as eStructuredDataTypeUnsignedInteger.
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     /// Retrieves the element at index \a idx from a StructuredData::Array if it
0246     /// is a Dictionary.
0247     ///
0248     /// \param[in] idx
0249     ///   The index of the element to retrieve.
0250     ///
0251     /// \return
0252     ///   If the element at index \a idx is a Dictionary, this method returns a
0253     ///   valid pointer to the Dictionary wrapped in a std::optional. If the
0254     ///   element is not a Dictionary or the index is invalid, this returns
0255     ///   std::nullopt. Note that the underlying Dictionary pointer is never
0256     ///   nullptr.
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 } // namespace lldb_private
0583 
0584 #endif // LLDB_UTILITY_STRUCTUREDDATA_H