180814287SRaphael Isemann //===-- StructuredData.cpp ------------------------------------------------===// 2f2a8bccfSPavel Labath // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f2a8bccfSPavel Labath // 7f2a8bccfSPavel Labath //===----------------------------------------------------------------------===// 8f2a8bccfSPavel Labath 9f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h" 10f2a8bccfSPavel Labath #include "lldb/Utility/FileSpec.h" 11f2a8bccfSPavel Labath #include "lldb/Utility/Status.h" 1211c0aab7SEugene Zemtsov #include "llvm/Support/MemoryBuffer.h" 13f2a8bccfSPavel Labath #include <cerrno> 14f2a8bccfSPavel Labath #include <cstdlib> 15f2a8bccfSPavel Labath #include <inttypes.h> 16f2a8bccfSPavel Labath 17f2a8bccfSPavel Labath using namespace lldb_private; 182783d817SJonas Devlieghere using namespace llvm; 19f2a8bccfSPavel Labath 2057b46882SJonas Devlieghere static StructuredData::ObjectSP ParseJSONValue(json::Value &value); 2157b46882SJonas Devlieghere static StructuredData::ObjectSP ParseJSONObject(json::Object *object); 2257b46882SJonas Devlieghere static StructuredData::ObjectSP ParseJSONArray(json::Array *array); 2357b46882SJonas Devlieghere 2457b46882SJonas Devlieghere StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) { 2557b46882SJonas Devlieghere llvm::Expected<json::Value> value = json::parse(json_text); 2657b46882SJonas Devlieghere if (!value) { 2757b46882SJonas Devlieghere llvm::consumeError(value.takeError()); 2857b46882SJonas Devlieghere return nullptr; 2957b46882SJonas Devlieghere } 3057b46882SJonas Devlieghere return ParseJSONValue(*value); 3157b46882SJonas Devlieghere } 32f2a8bccfSPavel Labath 33f2a8bccfSPavel Labath StructuredData::ObjectSP 34f2a8bccfSPavel Labath StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) { 35f2a8bccfSPavel Labath StructuredData::ObjectSP return_sp; 36f2a8bccfSPavel Labath 37f2a8bccfSPavel Labath auto buffer_or_error = llvm::MemoryBuffer::getFile(input_spec.GetPath()); 38f2a8bccfSPavel Labath if (!buffer_or_error) { 39f2a8bccfSPavel Labath error.SetErrorStringWithFormatv("could not open input file: {0} - {1}.", 40f2a8bccfSPavel Labath input_spec.GetPath(), 41f2a8bccfSPavel Labath buffer_or_error.getError().message()); 42f2a8bccfSPavel Labath return return_sp; 43f2a8bccfSPavel Labath } 4457b46882SJonas Devlieghere return ParseJSON(buffer_or_error.get()->getBuffer().str()); 45f2a8bccfSPavel Labath } 46f2a8bccfSPavel Labath 4757b46882SJonas Devlieghere static StructuredData::ObjectSP ParseJSONValue(json::Value &value) { 4857b46882SJonas Devlieghere if (json::Object *O = value.getAsObject()) 4957b46882SJonas Devlieghere return ParseJSONObject(O); 5057b46882SJonas Devlieghere 5157b46882SJonas Devlieghere if (json::Array *A = value.getAsArray()) 5257b46882SJonas Devlieghere return ParseJSONArray(A); 5357b46882SJonas Devlieghere 5457b46882SJonas Devlieghere std::string s; 5557b46882SJonas Devlieghere if (json::fromJSON(value, s)) 5657b46882SJonas Devlieghere return std::make_shared<StructuredData::String>(s); 5757b46882SJonas Devlieghere 5857b46882SJonas Devlieghere bool b; 5957b46882SJonas Devlieghere if (json::fromJSON(value, b)) 6057b46882SJonas Devlieghere return std::make_shared<StructuredData::Boolean>(b); 6157b46882SJonas Devlieghere 6257b46882SJonas Devlieghere int64_t i; 6357b46882SJonas Devlieghere if (json::fromJSON(value, i)) 6457b46882SJonas Devlieghere return std::make_shared<StructuredData::Integer>(i); 6557b46882SJonas Devlieghere 6657b46882SJonas Devlieghere double d; 6757b46882SJonas Devlieghere if (json::fromJSON(value, d)) 6857b46882SJonas Devlieghere return std::make_shared<StructuredData::Float>(d); 6957b46882SJonas Devlieghere 7057b46882SJonas Devlieghere return StructuredData::ObjectSP(); 7157b46882SJonas Devlieghere } 7257b46882SJonas Devlieghere 7357b46882SJonas Devlieghere static StructuredData::ObjectSP ParseJSONObject(json::Object *object) { 74a8f3ae7cSJonas Devlieghere auto dict_up = std::make_unique<StructuredData::Dictionary>(); 7557b46882SJonas Devlieghere for (auto &KV : *object) { 7657b46882SJonas Devlieghere StringRef key = KV.first; 7757b46882SJonas Devlieghere json::Value value = KV.second; 7857b46882SJonas Devlieghere if (StructuredData::ObjectSP value_sp = ParseJSONValue(value)) 79f2a8bccfSPavel Labath dict_up->AddItem(key, value_sp); 80f2a8bccfSPavel Labath } 81d1e3b23bSJonas Devlieghere return std::move(dict_up); 82f2a8bccfSPavel Labath } 83f2a8bccfSPavel Labath 8457b46882SJonas Devlieghere static StructuredData::ObjectSP ParseJSONArray(json::Array *array) { 85a8f3ae7cSJonas Devlieghere auto array_up = std::make_unique<StructuredData::Array>(); 8657b46882SJonas Devlieghere for (json::Value &value : *array) { 8757b46882SJonas Devlieghere if (StructuredData::ObjectSP value_sp = ParseJSONValue(value)) 88f2a8bccfSPavel Labath array_up->AddItem(value_sp); 89f2a8bccfSPavel Labath } 90d1e3b23bSJonas Devlieghere return std::move(array_up); 91f2a8bccfSPavel Labath } 92f2a8bccfSPavel Labath 93f2a8bccfSPavel Labath StructuredData::ObjectSP 94f2a8bccfSPavel Labath StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) { 95f2a8bccfSPavel Labath if (this->GetType() == lldb::eStructuredDataTypeDictionary) { 96f2a8bccfSPavel Labath std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.'); 97f2a8bccfSPavel Labath std::string key = match.first.str(); 98f2a8bccfSPavel Labath ObjectSP value = this->GetAsDictionary()->GetValueForKey(key); 99f2a8bccfSPavel Labath if (value.get()) { 10005097246SAdrian Prantl // Do we have additional words to descend? If not, return the value 10105097246SAdrian Prantl // we're at right now. 102f2a8bccfSPavel Labath if (match.second.empty()) { 103f2a8bccfSPavel Labath return value; 104f2a8bccfSPavel Labath } else { 105f2a8bccfSPavel Labath return value->GetObjectForDotSeparatedPath(match.second); 106f2a8bccfSPavel Labath } 107f2a8bccfSPavel Labath } 108f2a8bccfSPavel Labath return ObjectSP(); 109f2a8bccfSPavel Labath } 110f2a8bccfSPavel Labath 111f2a8bccfSPavel Labath if (this->GetType() == lldb::eStructuredDataTypeArray) { 112f2a8bccfSPavel Labath std::pair<llvm::StringRef, llvm::StringRef> match = path.split('['); 11365e5e278SJonas Devlieghere if (match.second.empty()) { 114f2a8bccfSPavel Labath return this->shared_from_this(); 115f2a8bccfSPavel Labath } 116f2a8bccfSPavel Labath errno = 0; 11765e5e278SJonas Devlieghere uint64_t val = strtoul(match.second.str().c_str(), nullptr, 10); 118f2a8bccfSPavel Labath if (errno == 0) { 119f2a8bccfSPavel Labath return this->GetAsArray()->GetItemAtIndex(val); 120f2a8bccfSPavel Labath } 121f2a8bccfSPavel Labath return ObjectSP(); 122f2a8bccfSPavel Labath } 123f2a8bccfSPavel Labath 124f2a8bccfSPavel Labath return this->shared_from_this(); 125f2a8bccfSPavel Labath } 126f2a8bccfSPavel Labath 127f2a8bccfSPavel Labath void StructuredData::Object::DumpToStdout(bool pretty_print) const { 1282783d817SJonas Devlieghere json::OStream stream(llvm::outs(), pretty_print ? 2 : 0); 1292783d817SJonas Devlieghere Serialize(stream); 130f2a8bccfSPavel Labath } 131f2a8bccfSPavel Labath 1322783d817SJonas Devlieghere void StructuredData::Array::Serialize(json::OStream &s) const { 1332783d817SJonas Devlieghere s.arrayBegin(); 134f2a8bccfSPavel Labath for (const auto &item_sp : m_items) { 1352783d817SJonas Devlieghere item_sp->Serialize(s); 1362783d817SJonas Devlieghere } 1372783d817SJonas Devlieghere s.arrayEnd(); 138f2a8bccfSPavel Labath } 139f2a8bccfSPavel Labath 1402783d817SJonas Devlieghere void StructuredData::Integer::Serialize(json::OStream &s) const { 1412783d817SJonas Devlieghere s.value(static_cast<int64_t>(m_value)); 142f2a8bccfSPavel Labath } 143f2a8bccfSPavel Labath 1442783d817SJonas Devlieghere void StructuredData::Float::Serialize(json::OStream &s) const { 1452783d817SJonas Devlieghere s.value(m_value); 146f2a8bccfSPavel Labath } 147f2a8bccfSPavel Labath 1482783d817SJonas Devlieghere void StructuredData::Boolean::Serialize(json::OStream &s) const { 1492783d817SJonas Devlieghere s.value(m_value); 150f2a8bccfSPavel Labath } 151f2a8bccfSPavel Labath 1522783d817SJonas Devlieghere void StructuredData::String::Serialize(json::OStream &s) const { 1532783d817SJonas Devlieghere s.value(m_value); 154f2a8bccfSPavel Labath } 155f2a8bccfSPavel Labath 1562783d817SJonas Devlieghere void StructuredData::Dictionary::Serialize(json::OStream &s) const { 1572783d817SJonas Devlieghere s.objectBegin(); 158f2a8bccfSPavel Labath for (const auto &pair : m_dict) { 159*642bc15dSRaphael Isemann s.attributeBegin(pair.first.GetStringRef()); 1602783d817SJonas Devlieghere pair.second->Serialize(s); 1612783d817SJonas Devlieghere s.attributeEnd(); 162f2a8bccfSPavel Labath } 1632783d817SJonas Devlieghere s.objectEnd(); 164f2a8bccfSPavel Labath } 165f2a8bccfSPavel Labath 1662783d817SJonas Devlieghere void StructuredData::Null::Serialize(json::OStream &s) const { 1672783d817SJonas Devlieghere s.value(nullptr); 168f2a8bccfSPavel Labath } 169f2a8bccfSPavel Labath 1702783d817SJonas Devlieghere void StructuredData::Generic::Serialize(json::OStream &s) const { 1712783d817SJonas Devlieghere s.value(llvm::formatv("{0:X}", m_object)); 172f2a8bccfSPavel Labath } 173