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