Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- StructuredData.h ----------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_UTILITY_STRUCTUREDDATA_H
10#define LLDB_UTILITY_STRUCTUREDDATA_H
11
12#include "llvm/ADT/StringRef.h"
13#include "llvm/Support/JSON.h"
14
15#include "lldb/Utility/ConstString.h"
16#include "lldb/Utility/FileSpec.h"
17#include "lldb/Utility/Stream.h"
18#include "lldb/lldb-enumerations.h"
19
20#include <cassert>
21#include <cstddef>
22#include <cstdint>
23#include <functional>
24#include <map>
25#include <memory>
26#include <string>
27#include <type_traits>
28#include <utility>
29#include <vector>
30
31namespace lldb_private {
32class Status;
33}
34
35namespace lldb_private {
36
37/// \class StructuredData StructuredData.h "lldb/Utility/StructuredData.h"
38/// A class which can hold structured data
39///
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.
44///
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.
49
50class StructuredData {
51public:
52 class Object;
53 class Array;
54 class Integer;
55 class Float;
56 class Boolean;
57 class String;
58 class Dictionary;
59 class Generic;
60
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;
69
70 class Object : public std::enable_shared_from_this<Object> {
71 public:
72 Object(lldb::StructuredDataType t = lldb::eStructuredDataTypeInvalid)
73 : m_type(t) {}
74
75 virtual ~Object() = default;
76
77 virtual bool IsValid() const { return true; }
78
79 virtual void Clear() { m_type = lldb::eStructuredDataTypeInvalid; }
80
81 lldb::StructuredDataType GetType() const { return m_type; }
82
83 void SetType(lldb::StructuredDataType t) { m_type = t; }
84
85 Array *GetAsArray() {
86 return ((m_type == lldb::eStructuredDataTypeArray)
87 ? static_cast<Array *>(this)
88 : nullptr);
89 }
90
91 Dictionary *GetAsDictionary() {
92 return ((m_type == lldb::eStructuredDataTypeDictionary)
93 ? static_cast<Dictionary *>(this)
94 : nullptr);
95 }
96
97 Integer *GetAsInteger() {
98 return ((m_type == lldb::eStructuredDataTypeInteger)
99 ? static_cast<Integer *>(this)
100 : nullptr);
101 }
102
103 uint64_t GetIntegerValue(uint64_t fail_value = 0) {
104 Integer *integer = GetAsInteger();
105 return ((integer != nullptr) ? integer->GetValue() : fail_value);
106 }
107
108 Float *GetAsFloat() {
109 return ((m_type == lldb::eStructuredDataTypeFloat)
110 ? static_cast<Float *>(this)
111 : nullptr);
112 }
113
114 double GetFloatValue(double fail_value = 0.0) {
115 Float *f = GetAsFloat();
116 return ((f != nullptr) ? f->GetValue() : fail_value);
117 }
118
119 Boolean *GetAsBoolean() {
120 return ((m_type == lldb::eStructuredDataTypeBoolean)
121 ? static_cast<Boolean *>(this)
122 : nullptr);
123 }
124
125 bool GetBooleanValue(bool fail_value = false) {
126 Boolean *b = GetAsBoolean();
127 return ((b != nullptr) ? b->GetValue() : fail_value);
128 }
129
130 String *GetAsString() {
131 return ((m_type == lldb::eStructuredDataTypeString)
132 ? static_cast<String *>(this)
133 : nullptr);
134 }
135
136 llvm::StringRef GetStringValue(const char *fail_value = nullptr) {
137 String *s = GetAsString();
138 if (s)
139 return s->GetValue();
140
141 return fail_value;
142 }
143
144 Generic *GetAsGeneric() {
145 return ((m_type == lldb::eStructuredDataTypeGeneric)
146 ? static_cast<Generic *>(this)
147 : nullptr);
148 }
149
150 ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);
151
152 void DumpToStdout(bool pretty_print = true) const;
153
154 virtual void Serialize(llvm::json::OStream &s) const = 0;
155
156 void Dump(lldb_private::Stream &s, bool pretty_print = true) const {
157 llvm::json::OStream jso(s.AsRawOstream(), pretty_print ? 2 : 0);
158 Serialize(jso);
159 }
160
161 virtual void GetDescription(lldb_private::Stream &s) const {
162 s.IndentMore();
163 Dump(s, false);
164 s.IndentLess();
165 }
166
167 private:
168 lldb::StructuredDataType m_type;
169 };
170
171 class Array : public Object {
172 public:
173 Array() : Object(lldb::eStructuredDataTypeArray) {}
174
175 ~Array() override = default;
176
177 bool
178 ForEach(std::function<bool(Object *object)> const &foreach_callback) const {
179 for (const auto &object_sp : m_items) {
180 if (!foreach_callback(object_sp.get()))
181 return false;
182 }
183 return true;
184 }
185
186 size_t GetSize() const { return m_items.size(); }
187
188 ObjectSP operator[](size_t idx) {
189 if (idx < m_items.size())
190 return m_items[idx];
191 return ObjectSP();
192 }
193
194 ObjectSP GetItemAtIndex(size_t idx) const {
195 assert(idx < GetSize());
196 if (idx < m_items.size())
197 return m_items[idx];
198 return ObjectSP();
199 }
200
201 template <class IntType>
202 bool GetItemAtIndexAsInteger(size_t idx, IntType &result) const {
203 ObjectSP value_sp = GetItemAtIndex(idx);
204 if (value_sp.get()) {
205 if (auto int_value = value_sp->GetAsInteger()) {
206 result = static_cast<IntType>(int_value->GetValue());
207 return true;
208 }
209 }
210 return false;
211 }
212
213 template <class IntType>
214 bool GetItemAtIndexAsInteger(size_t idx, IntType &result,
215 IntType default_val) const {
216 bool success = GetItemAtIndexAsInteger(idx, result);
217 if (!success)
218 result = default_val;
219 return success;
220 }
221
222 bool GetItemAtIndexAsString(size_t idx, llvm::StringRef &result) const {
223 ObjectSP value_sp = GetItemAtIndex(idx);
224 if (value_sp.get()) {
225 if (auto string_value = value_sp->GetAsString()) {
226 result = string_value->GetValue();
227 return true;
228 }
229 }
230 return false;
231 }
232
233 bool GetItemAtIndexAsString(size_t idx, llvm::StringRef &result,
234 llvm::StringRef default_val) const {
235 bool success = GetItemAtIndexAsString(idx, result);
236 if (!success)
237 result = default_val;
238 return success;
239 }
240
241 bool GetItemAtIndexAsString(size_t idx, ConstString &result) const {
242 ObjectSP value_sp = GetItemAtIndex(idx);
243 if (value_sp.get()) {
244 if (auto string_value = value_sp->GetAsString()) {
245 result = ConstString(string_value->GetValue());
246 return true;
247 }
248 }
249 return false;
250 }
251
252 bool GetItemAtIndexAsString(size_t idx, ConstString &result,
253 const char *default_val) const {
254 bool success = GetItemAtIndexAsString(idx, result);
255 if (!success)
256 result.SetCString(default_val);
257 return success;
258 }
259
260 bool GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const {
261 result = nullptr;
262 ObjectSP value_sp = GetItemAtIndex(idx);
263 if (value_sp.get()) {
264 result = value_sp->GetAsDictionary();
265 return (result != nullptr);
266 }
267 return false;
268 }
269
270 bool GetItemAtIndexAsArray(size_t idx, Array *&result) const {
271 result = nullptr;
272 ObjectSP value_sp = GetItemAtIndex(idx);
273 if (value_sp.get()) {
274 result = value_sp->GetAsArray();
275 return (result != nullptr);
276 }
277 return false;
278 }
279
280 void Push(const ObjectSP &item) { m_items.push_back(item); }
281
282 void AddItem(const ObjectSP &item) { m_items.push_back(item); }
283
284 void Serialize(llvm::json::OStream &s) const override;
285
286 void GetDescription(lldb_private::Stream &s) const override;
287
288 protected:
289 typedef std::vector<ObjectSP> collection;
290 collection m_items;
291 };
292
293 class Integer : public Object {
294 public:
295 Integer(uint64_t i = 0)
296 : Object(lldb::eStructuredDataTypeInteger), m_value(i) {}
297
298 ~Integer() override = default;
299
300 void SetValue(uint64_t value) { m_value = value; }
301
302 uint64_t GetValue() { return m_value; }
303
304 void Serialize(llvm::json::OStream &s) const override;
305
306 void GetDescription(lldb_private::Stream &s) const override;
307
308 protected:
309 uint64_t m_value;
310 };
311
312 class Float : public Object {
313 public:
314 Float(double d = 0.0)
315 : Object(lldb::eStructuredDataTypeFloat), m_value(d) {}
316
317 ~Float() override = default;
318
319 void SetValue(double value) { m_value = value; }
320
321 double GetValue() { return m_value; }
322
323 void Serialize(llvm::json::OStream &s) const override;
324
325 void GetDescription(lldb_private::Stream &s) const override;
326
327 protected:
328 double m_value;
329 };
330
331 class Boolean : public Object {
332 public:
333 Boolean(bool b = false)
334 : Object(lldb::eStructuredDataTypeBoolean), m_value(b) {}
335
336 ~Boolean() override = default;
337
338 void SetValue(bool value) { m_value = value; }
339
340 bool GetValue() { return m_value; }
341
342 void Serialize(llvm::json::OStream &s) const override;
343
344 void GetDescription(lldb_private::Stream &s) const override;
345
346 protected:
347 bool m_value;
348 };
349
350 class String : public Object {
351 public:
352 String() : Object(lldb::eStructuredDataTypeString) {}
353 explicit String(llvm::StringRef S)
354 : Object(lldb::eStructuredDataTypeString), m_value(S) {}
355
356 void SetValue(llvm::StringRef S) { m_value = std::string(S); }
357
358 llvm::StringRef GetValue() { return m_value; }
359
360 void Serialize(llvm::json::OStream &s) const override;
361
362 void GetDescription(lldb_private::Stream &s) const override;
363
364 protected:
365 std::string m_value;
366 };
367
368 class Dictionary : public Object {
369 public:
370 Dictionary() : Object(lldb::eStructuredDataTypeDictionary) {}
371
372 Dictionary(ObjectSP obj_sp) : Object(lldb::eStructuredDataTypeDictionary) {
373 if (!obj_sp || obj_sp->GetType() != lldb::eStructuredDataTypeDictionary) {
374 SetType(lldb::eStructuredDataTypeInvalid);
375 return;
376 }
377
378 Dictionary *dict = obj_sp->GetAsDictionary();
379 m_dict = dict->m_dict;
380 }
381
382 ~Dictionary() override = default;
383
384 size_t GetSize() const { return m_dict.size(); }
385
386 void ForEach(std::function<bool(ConstString key, Object *object)> const
387 &callback) const {
388 for (const auto &pair : m_dict) {
389 if (!callback(pair.first, pair.second.get()))
390 break;
391 }
392 }
393
394 ArraySP GetKeys() const {
395 auto array_sp = std::make_shared<Array>();
396 collection::const_iterator iter;
397 for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
398 auto key_object_sp = std::make_shared<String>();
399 key_object_sp->SetValue(iter->first.AsCString());
400 array_sp->Push(key_object_sp);
401 }
402 return array_sp;
403 }
404
405 ObjectSP GetValueForKey(llvm::StringRef key) const {
406 ObjectSP value_sp;
407 if (!key.empty()) {
408 ConstString key_cs(key);
409 collection::const_iterator iter = m_dict.find(key_cs);
410 if (iter != m_dict.end())
411 value_sp = iter->second;
412 }
413 return value_sp;
414 }
415
416 bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const {
417 bool success = false;
418 ObjectSP value_sp = GetValueForKey(key);
419 if (value_sp.get()) {
420 Boolean *result_ptr = value_sp->GetAsBoolean();
421 if (result_ptr) {
422 result = result_ptr->GetValue();
423 success = true;
424 }
425 }
426 return success;
427 }
428 template <class IntType>
429 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
430 ObjectSP value_sp = GetValueForKey(key);
431 if (value_sp) {
432 if (auto int_value = value_sp->GetAsInteger()) {
433 result = static_cast<IntType>(int_value->GetValue());
434 return true;
435 }
436 }
437 return false;
438 }
439
440 template <class IntType>
441 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result,
442 IntType default_val) const {
443 bool success = GetValueForKeyAsInteger<IntType>(key, result);
444 if (!success)
445 result = default_val;
446 return success;
447 }
448
449 bool GetValueForKeyAsString(llvm::StringRef key,
450 llvm::StringRef &result) const {
451 ObjectSP value_sp = GetValueForKey(key);
452 if (value_sp.get()) {
453 if (auto string_value = value_sp->GetAsString()) {
454 result = string_value->GetValue();
455 return true;
456 }
457 }
458 return false;
459 }
460
461 bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result,
462 const char *default_val) const {
463 bool success = GetValueForKeyAsString(key, result);
464 if (!success) {
465 if (default_val)
466 result = default_val;
467 else
468 result = llvm::StringRef();
469 }
470 return success;
471 }
472
473 bool GetValueForKeyAsString(llvm::StringRef key,
474 ConstString &result) const {
475 ObjectSP value_sp = GetValueForKey(key);
476 if (value_sp.get()) {
477 if (auto string_value = value_sp->GetAsString()) {
478 result = ConstString(string_value->GetValue());
479 return true;
480 }
481 }
482 return false;
483 }
484
485 bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result,
486 const char *default_val) const {
487 bool success = GetValueForKeyAsString(key, result);
488 if (!success)
489 result.SetCString(default_val);
490 return success;
491 }
492
493 bool GetValueForKeyAsDictionary(llvm::StringRef key,
494 Dictionary *&result) const {
495 result = nullptr;
496 ObjectSP value_sp = GetValueForKey(key);
497 if (value_sp.get()) {
498 result = value_sp->GetAsDictionary();
499 return (result != nullptr);
500 }
501 return false;
502 }
503
504 bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const {
505 result = nullptr;
506 ObjectSP value_sp = GetValueForKey(key);
507 if (value_sp.get()) {
508 result = value_sp->GetAsArray();
509 return (result != nullptr);
510 }
511 return false;
512 }
513
514 bool HasKey(llvm::StringRef key) const {
515 ConstString key_cs(key);
516 collection::const_iterator search = m_dict.find(key_cs);
517 return search != m_dict.end();
518 }
519
520 void AddItem(llvm::StringRef key, ObjectSP value_sp) {
521 ConstString key_cs(key);
522 m_dict[key_cs] = std::move(value_sp);
523 }
524
525 void AddIntegerItem(llvm::StringRef key, uint64_t value) {
526 AddItem(key, std::make_shared<Integer>(value));
527 }
528
529 void AddFloatItem(llvm::StringRef key, double value) {
530 AddItem(key, std::make_shared<Float>(value));
531 }
532
533 void AddStringItem(llvm::StringRef key, llvm::StringRef value) {
534 AddItem(key, std::make_shared<String>(std::move(value)));
535 }
536
537 void AddBooleanItem(llvm::StringRef key, bool value) {
538 AddItem(key, std::make_shared<Boolean>(value));
539 }
540
541 void Serialize(llvm::json::OStream &s) const override;
542
543 void GetDescription(lldb_private::Stream &s) const override;
544
545 protected:
546 typedef std::map<ConstString, ObjectSP> collection;
547 collection m_dict;
548 };
549
550 class Null : public Object {
551 public:
552 Null() : Object(lldb::eStructuredDataTypeNull) {}
553
554 ~Null() override = default;
555
556 bool IsValid() const override { return false; }
557
558 void Serialize(llvm::json::OStream &s) const override;
559
560 void GetDescription(lldb_private::Stream &s) const override;
561 };
562
563 class Generic : public Object {
564 public:
565 explicit Generic(void *object = nullptr)
566 : Object(lldb::eStructuredDataTypeGeneric), m_object(object) {}
567
568 void SetValue(void *value) { m_object = value; }
569
570 void *GetValue() const { return m_object; }
571
572 bool IsValid() const override { return m_object != nullptr; }
573
574 void Serialize(llvm::json::OStream &s) const override;
575
576 void GetDescription(lldb_private::Stream &s) const override;
577
578 private:
579 void *m_object;
580 };
581
582 static ObjectSP ParseJSON(llvm::StringRef json_text);
583 static ObjectSP ParseJSONFromFile(const FileSpec &file, Status &error);
584 static bool IsRecordType(const ObjectSP object_sp);
585};
586
587} // namespace lldb_private
588
589#endif // LLDB_UTILITY_STRUCTUREDDATA_H
590

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of lldb/include/lldb/Utility/StructuredData.h