diff options
Diffstat (limited to 'lldb/source/Utility/StructuredData.cpp')
| -rw-r--r-- | lldb/source/Utility/StructuredData.cpp | 176 | 
1 files changed, 176 insertions, 0 deletions
diff --git a/lldb/source/Utility/StructuredData.cpp b/lldb/source/Utility/StructuredData.cpp new file mode 100644 index 000000000000..783a08082174 --- /dev/null +++ b/lldb/source/Utility/StructuredData.cpp @@ -0,0 +1,176 @@ +//===---------------------StructuredData.cpp ---------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/StructuredData.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/StreamString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/MemoryBuffer.h" +#include <cerrno> +#include <cstdlib> +#include <inttypes.h> +#include <limits> + +using namespace lldb_private; +using namespace llvm; + +static StructuredData::ObjectSP ParseJSONValue(json::Value &value); +static StructuredData::ObjectSP ParseJSONObject(json::Object *object); +static StructuredData::ObjectSP ParseJSONArray(json::Array *array); + +StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) { +  llvm::Expected<json::Value> value = json::parse(json_text); +  if (!value) { +    llvm::consumeError(value.takeError()); +    return nullptr; +  } +  return ParseJSONValue(*value); +} + +StructuredData::ObjectSP +StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) { +  StructuredData::ObjectSP return_sp; + +  auto buffer_or_error = llvm::MemoryBuffer::getFile(input_spec.GetPath()); +  if (!buffer_or_error) { +    error.SetErrorStringWithFormatv("could not open input file: {0} - {1}.", +                                    input_spec.GetPath(), +                                    buffer_or_error.getError().message()); +    return return_sp; +  } +  return ParseJSON(buffer_or_error.get()->getBuffer().str()); +} + +static StructuredData::ObjectSP ParseJSONValue(json::Value &value) { +  if (json::Object *O = value.getAsObject()) +    return ParseJSONObject(O); + +  if (json::Array *A = value.getAsArray()) +    return ParseJSONArray(A); + +  std::string s; +  if (json::fromJSON(value, s)) +    return std::make_shared<StructuredData::String>(s); + +  bool b; +  if (json::fromJSON(value, b)) +    return std::make_shared<StructuredData::Boolean>(b); + +  int64_t i; +  if (json::fromJSON(value, i)) +    return std::make_shared<StructuredData::Integer>(i); + +  double d; +  if (json::fromJSON(value, d)) +    return std::make_shared<StructuredData::Float>(d); + +  return StructuredData::ObjectSP(); +} + +static StructuredData::ObjectSP ParseJSONObject(json::Object *object) { +  auto dict_up = std::make_unique<StructuredData::Dictionary>(); +  for (auto &KV : *object) { +    StringRef key = KV.first; +    json::Value value = KV.second; +    if (StructuredData::ObjectSP value_sp = ParseJSONValue(value)) +      dict_up->AddItem(key, value_sp); +  } +  return dict_up; +} + +static StructuredData::ObjectSP ParseJSONArray(json::Array *array) { +  auto array_up = std::make_unique<StructuredData::Array>(); +  for (json::Value &value : *array) { +    if (StructuredData::ObjectSP value_sp = ParseJSONValue(value)) +      array_up->AddItem(value_sp); +  } +  return array_up; +} + +StructuredData::ObjectSP +StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) { +  if (this->GetType() == lldb::eStructuredDataTypeDictionary) { +    std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.'); +    std::string key = match.first.str(); +    ObjectSP value = this->GetAsDictionary()->GetValueForKey(key); +    if (value.get()) { +      // Do we have additional words to descend?  If not, return the value +      // we're at right now. +      if (match.second.empty()) { +        return value; +      } else { +        return value->GetObjectForDotSeparatedPath(match.second); +      } +    } +    return ObjectSP(); +  } + +  if (this->GetType() == lldb::eStructuredDataTypeArray) { +    std::pair<llvm::StringRef, llvm::StringRef> match = path.split('['); +    if (match.second.empty()) { +      return this->shared_from_this(); +    } +    errno = 0; +    uint64_t val = strtoul(match.second.str().c_str(), nullptr, 10); +    if (errno == 0) { +      return this->GetAsArray()->GetItemAtIndex(val); +    } +    return ObjectSP(); +  } + +  return this->shared_from_this(); +} + +void StructuredData::Object::DumpToStdout(bool pretty_print) const { +  json::OStream stream(llvm::outs(), pretty_print ? 2 : 0); +  Serialize(stream); +} + +void StructuredData::Array::Serialize(json::OStream &s) const { +  s.arrayBegin(); +  for (const auto &item_sp : m_items) { +    item_sp->Serialize(s); +  } +  s.arrayEnd(); +} + +void StructuredData::Integer::Serialize(json::OStream &s) const { +  s.value(static_cast<int64_t>(m_value)); +} + +void StructuredData::Float::Serialize(json::OStream &s) const { +  s.value(m_value); +} + +void StructuredData::Boolean::Serialize(json::OStream &s) const { +  s.value(m_value); +} + +void StructuredData::String::Serialize(json::OStream &s) const { +  s.value(m_value); +} + +void StructuredData::Dictionary::Serialize(json::OStream &s) const { +  s.objectBegin(); +  for (const auto &pair : m_dict) { +    s.attributeBegin(pair.first.AsCString()); +    pair.second->Serialize(s); +    s.attributeEnd(); +  } +  s.objectEnd(); +} + +void StructuredData::Null::Serialize(json::OStream &s) const { +  s.value(nullptr); +} + +void StructuredData::Generic::Serialize(json::OStream &s) const { +  s.value(llvm::formatv("{0:X}", m_object)); +}  | 
