1 //===-- StructuredData.h ----------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef liblldb_StructuredData_h_
10 #define liblldb_StructuredData_h_
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/Support/JSON.h"
15 #include "lldb/Utility/ConstString.h"
16 #include "lldb/Utility/FileSpec.h"
17 #include "lldb/Utility/Stream.h"
18 #include "lldb/lldb-enumerations.h"
27 #include <type_traits>
31 namespace lldb_private {
35 namespace lldb_private {
37 /// \class StructuredData StructuredData.h "lldb/Utility/StructuredData.h"
38 /// A class which can hold structured data
40 /// The StructuredData class is designed to hold the data from a JSON or plist
41 /// style file -- a serialized data structure with dictionaries (maps,
42 /// hashes), arrays, and concrete values like integers, floating point
43 /// numbers, strings, booleans.
45 /// StructuredData does not presuppose any knowledge of the schema for the
46 /// data it is holding; it can parse JSON data, for instance, and other parts
47 /// of lldb can iterate through the parsed data set to find keys and values
48 /// that may be present.
50 class StructuredData {
61 typedef std::shared_ptr<Object> ObjectSP;
62 typedef std::shared_ptr<Array> ArraySP;
63 typedef std::shared_ptr<Integer> IntegerSP;
64 typedef std::shared_ptr<Float> FloatSP;
65 typedef std::shared_ptr<Boolean> BooleanSP;
66 typedef std::shared_ptr<String> StringSP;
67 typedef std::shared_ptr<Dictionary> DictionarySP;
68 typedef std::shared_ptr<Generic> GenericSP;
70 class Object : public std::enable_shared_from_this<Object> {
72 Object(lldb::StructuredDataType t = lldb::eStructuredDataTypeInvalid)
75 virtual ~Object() = default;
77 virtual bool IsValid() const { return true; }
79 virtual void Clear() { m_type = lldb::eStructuredDataTypeInvalid; }
81 lldb::StructuredDataType GetType() const { return m_type; }
83 void SetType(lldb::StructuredDataType t) { m_type = t; }
86 return ((m_type == lldb::eStructuredDataTypeArray)
87 ? static_cast<Array *>(this)
91 Dictionary *GetAsDictionary() {
92 return ((m_type == lldb::eStructuredDataTypeDictionary)
93 ? static_cast<Dictionary *>(this)
97 Integer *GetAsInteger() {
98 return ((m_type == lldb::eStructuredDataTypeInteger)
99 ? static_cast<Integer *>(this)
103 uint64_t GetIntegerValue(uint64_t fail_value = 0) {
104 Integer *integer = GetAsInteger();
105 return ((integer != nullptr) ? integer->GetValue() : fail_value);
108 Float *GetAsFloat() {
109 return ((m_type == lldb::eStructuredDataTypeFloat)
110 ? static_cast<Float *>(this)
114 double GetFloatValue(double fail_value = 0.0) {
115 Float *f = GetAsFloat();
116 return ((f != nullptr) ? f->GetValue() : fail_value);
119 Boolean *GetAsBoolean() {
120 return ((m_type == lldb::eStructuredDataTypeBoolean)
121 ? static_cast<Boolean *>(this)
125 bool GetBooleanValue(bool fail_value = false) {
126 Boolean *b = GetAsBoolean();
127 return ((b != nullptr) ? b->GetValue() : fail_value);
130 String *GetAsString() {
131 return ((m_type == lldb::eStructuredDataTypeString)
132 ? static_cast<String *>(this)
136 llvm::StringRef GetStringValue(const char *fail_value = nullptr) {
137 String *s = GetAsString();
139 return s->GetValue();
144 Generic *GetAsGeneric() {
145 return ((m_type == lldb::eStructuredDataTypeGeneric)
146 ? static_cast<Generic *>(this)
150 ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);
152 void DumpToStdout(bool pretty_print = true) const;
154 virtual void Serialize(llvm::json::OStream &s) const = 0;
156 void Dump(lldb_private::Stream &s, bool pretty_print = true) const {
157 llvm::json::OStream jso(s.AsRawOstream(), pretty_print ? 2 : 0);
162 lldb::StructuredDataType m_type;
165 class Array : public Object {
167 Array() : Object(lldb::eStructuredDataTypeArray) {}
169 ~Array() override = default;
172 ForEach(std::function<bool(Object *object)> const &foreach_callback) const {
173 for (const auto &object_sp : m_items) {
174 if (!foreach_callback(object_sp.get()))
180 size_t GetSize() const { return m_items.size(); }
182 ObjectSP operator[](size_t idx) {
183 if (idx < m_items.size())
188 ObjectSP GetItemAtIndex(size_t idx) const {
189 assert(idx < GetSize());
190 if (idx < m_items.size())
195 template <class IntType>
196 bool GetItemAtIndexAsInteger(size_t idx, IntType &result) const {
197 ObjectSP value_sp = GetItemAtIndex(idx);
198 if (value_sp.get()) {
199 if (auto int_value = value_sp->GetAsInteger()) {
200 result = static_cast<IntType>(int_value->GetValue());
207 template <class IntType>
208 bool GetItemAtIndexAsInteger(size_t idx, IntType &result,
209 IntType default_val) const {
210 bool success = GetItemAtIndexAsInteger(idx, result);
212 result = default_val;
216 bool GetItemAtIndexAsString(size_t idx, llvm::StringRef &result) const {
217 ObjectSP value_sp = GetItemAtIndex(idx);
218 if (value_sp.get()) {
219 if (auto string_value = value_sp->GetAsString()) {
220 result = string_value->GetValue();
227 bool GetItemAtIndexAsString(size_t idx, llvm::StringRef &result,
228 llvm::StringRef default_val) const {
229 bool success = GetItemAtIndexAsString(idx, result);
231 result = default_val;
235 bool GetItemAtIndexAsString(size_t idx, ConstString &result) const {
236 ObjectSP value_sp = GetItemAtIndex(idx);
237 if (value_sp.get()) {
238 if (auto string_value = value_sp->GetAsString()) {
239 result = ConstString(string_value->GetValue());
246 bool GetItemAtIndexAsString(size_t idx, ConstString &result,
247 const char *default_val) const {
248 bool success = GetItemAtIndexAsString(idx, result);
250 result.SetCString(default_val);
254 bool GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const {
256 ObjectSP value_sp = GetItemAtIndex(idx);
257 if (value_sp.get()) {
258 result = value_sp->GetAsDictionary();
259 return (result != nullptr);
264 bool GetItemAtIndexAsArray(size_t idx, Array *&result) const {
266 ObjectSP value_sp = GetItemAtIndex(idx);
267 if (value_sp.get()) {
268 result = value_sp->GetAsArray();
269 return (result != nullptr);
274 void Push(ObjectSP item) { m_items.push_back(item); }
276 void AddItem(ObjectSP item) { m_items.push_back(item); }
278 void Serialize(llvm::json::OStream &s) const override;
281 typedef std::vector<ObjectSP> collection;
285 class Integer : public Object {
287 Integer(uint64_t i = 0)
288 : Object(lldb::eStructuredDataTypeInteger), m_value(i) {}
290 ~Integer() override = default;
292 void SetValue(uint64_t value) { m_value = value; }
294 uint64_t GetValue() { return m_value; }
296 void Serialize(llvm::json::OStream &s) const override;
302 class Float : public Object {
304 Float(double d = 0.0)
305 : Object(lldb::eStructuredDataTypeFloat), m_value(d) {}
307 ~Float() override = default;
309 void SetValue(double value) { m_value = value; }
311 double GetValue() { return m_value; }
313 void Serialize(llvm::json::OStream &s) const override;
319 class Boolean : public Object {
321 Boolean(bool b = false)
322 : Object(lldb::eStructuredDataTypeBoolean), m_value(b) {}
324 ~Boolean() override = default;
326 void SetValue(bool value) { m_value = value; }
328 bool GetValue() { return m_value; }
330 void Serialize(llvm::json::OStream &s) const override;
336 class String : public Object {
338 String() : Object(lldb::eStructuredDataTypeString) {}
339 explicit String(llvm::StringRef S)
340 : Object(lldb::eStructuredDataTypeString), m_value(S) {}
342 void SetValue(llvm::StringRef S) { m_value = S; }
344 llvm::StringRef GetValue() { return m_value; }
346 void Serialize(llvm::json::OStream &s) const override;
352 class Dictionary : public Object {
354 Dictionary() : Object(lldb::eStructuredDataTypeDictionary), m_dict() {}
356 ~Dictionary() override = default;
358 size_t GetSize() const { return m_dict.size(); }
360 void ForEach(std::function<bool(ConstString key, Object *object)> const
362 for (const auto &pair : m_dict) {
363 if (!callback(pair.first, pair.second.get()))
368 ObjectSP GetKeys() const {
369 auto object_sp = std::make_shared<Array>();
370 collection::const_iterator iter;
371 for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
372 auto key_object_sp = std::make_shared<String>();
373 key_object_sp->SetValue(iter->first.AsCString());
374 object_sp->Push(key_object_sp);
379 ObjectSP GetValueForKey(llvm::StringRef key) const {
382 ConstString key_cs(key);
383 collection::const_iterator iter = m_dict.find(key_cs);
384 if (iter != m_dict.end())
385 value_sp = iter->second;
390 bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const {
391 bool success = false;
392 ObjectSP value_sp = GetValueForKey(key);
393 if (value_sp.get()) {
394 Boolean *result_ptr = value_sp->GetAsBoolean();
396 result = result_ptr->GetValue();
402 template <class IntType>
403 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
404 ObjectSP value_sp = GetValueForKey(key);
406 if (auto int_value = value_sp->GetAsInteger()) {
407 result = static_cast<IntType>(int_value->GetValue());
414 template <class IntType>
415 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result,
416 IntType default_val) const {
417 bool success = GetValueForKeyAsInteger<IntType>(key, result);
419 result = default_val;
423 bool GetValueForKeyAsString(llvm::StringRef key,
424 llvm::StringRef &result) const {
425 ObjectSP value_sp = GetValueForKey(key);
426 if (value_sp.get()) {
427 if (auto string_value = value_sp->GetAsString()) {
428 result = string_value->GetValue();
435 bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result,
436 const char *default_val) const {
437 bool success = GetValueForKeyAsString(key, result);
440 result = default_val;
442 result = llvm::StringRef();
447 bool GetValueForKeyAsString(llvm::StringRef key,
448 ConstString &result) const {
449 ObjectSP value_sp = GetValueForKey(key);
450 if (value_sp.get()) {
451 if (auto string_value = value_sp->GetAsString()) {
452 result = ConstString(string_value->GetValue());
459 bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result,
460 const char *default_val) const {
461 bool success = GetValueForKeyAsString(key, result);
463 result.SetCString(default_val);
467 bool GetValueForKeyAsDictionary(llvm::StringRef key,
468 Dictionary *&result) const {
470 ObjectSP value_sp = GetValueForKey(key);
471 if (value_sp.get()) {
472 result = value_sp->GetAsDictionary();
473 return (result != nullptr);
478 bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const {
480 ObjectSP value_sp = GetValueForKey(key);
481 if (value_sp.get()) {
482 result = value_sp->GetAsArray();
483 return (result != nullptr);
488 bool HasKey(llvm::StringRef key) const {
489 ConstString key_cs(key);
490 collection::const_iterator search = m_dict.find(key_cs);
491 return search != m_dict.end();
494 void AddItem(llvm::StringRef key, ObjectSP value_sp) {
495 ConstString key_cs(key);
496 m_dict[key_cs] = value_sp;
499 void AddIntegerItem(llvm::StringRef key, uint64_t value) {
500 AddItem(key, std::make_shared<Integer>(value));
503 void AddFloatItem(llvm::StringRef key, double value) {
504 AddItem(key, std::make_shared<Float>(value));
507 void AddStringItem(llvm::StringRef key, llvm::StringRef value) {
508 AddItem(key, std::make_shared<String>(std::move(value)));
511 void AddBooleanItem(llvm::StringRef key, bool value) {
512 AddItem(key, std::make_shared<Boolean>(value));
515 void Serialize(llvm::json::OStream &s) const override;
518 typedef std::map<ConstString, ObjectSP> collection;
522 class Null : public Object {
524 Null() : Object(lldb::eStructuredDataTypeNull) {}
526 ~Null() override = default;
528 bool IsValid() const override { return false; }
530 void Serialize(llvm::json::OStream &s) const override;
533 class Generic : public Object {
535 explicit Generic(void *object = nullptr)
536 : Object(lldb::eStructuredDataTypeGeneric), m_object(object) {}
538 void SetValue(void *value) { m_object = value; }
540 void *GetValue() const { return m_object; }
542 bool IsValid() const override { return m_object != nullptr; }
544 void Serialize(llvm::json::OStream &s) const override;
550 static ObjectSP ParseJSON(std::string json_text);
551 static ObjectSP ParseJSONFromFile(const FileSpec &file, Status &error);
554 } // namespace lldb_private
556 #endif // liblldb_StructuredData_h_