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