summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp286
1 files changed, 286 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp b/contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp
new file mode 100644
index 0000000..9fc0535
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp
@@ -0,0 +1,286 @@
+//===---------------------StructuredData.cpp ---------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/StructuredData.h"
+#include "lldb/Utility/DataBuffer.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/JSON.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/StreamString.h"
+#include "llvm/ADT/STLExtras.h" // for make_unique
+#include <cerrno>
+#include <cstdlib>
+#include <inttypes.h>
+#include <limits> // for numeric_limits
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Functions that use a JSONParser to parse JSON into StructuredData
+//----------------------------------------------------------------------
+static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser);
+static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser);
+static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser);
+
+StructuredData::ObjectSP
+StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) {
+ StructuredData::ObjectSP return_sp;
+ if (!input_spec.Exists()) {
+ error.SetErrorStringWithFormatv("input file {0} does not exist.",
+ input_spec);
+ return 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;
+ }
+
+ JSONParser json_parser(buffer_or_error.get()->getBuffer());
+ return_sp = ParseJSONValue(json_parser);
+ return return_sp;
+}
+
+static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) {
+ // The "JSONParser::Token::ObjectStart" token should have already been
+ // consumed by the time this function is called
+ auto dict_up = llvm::make_unique<StructuredData::Dictionary>();
+
+ std::string value;
+ std::string key;
+ while (1) {
+ JSONParser::Token token = json_parser.GetToken(value);
+
+ if (token == JSONParser::Token::String) {
+ key.swap(value);
+ token = json_parser.GetToken(value);
+ if (token == JSONParser::Token::Colon) {
+ StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
+ if (value_sp)
+ dict_up->AddItem(key, value_sp);
+ else
+ break;
+ }
+ } else if (token == JSONParser::Token::ObjectEnd) {
+ return StructuredData::ObjectSP(dict_up.release());
+ } else if (token == JSONParser::Token::Comma) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ return StructuredData::ObjectSP();
+}
+
+static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser) {
+ // The "JSONParser::Token::ObjectStart" token should have already been
+ // consumed
+ // by the time this function is called
+ auto array_up = llvm::make_unique<StructuredData::Array>();
+
+ std::string value;
+ std::string key;
+ while (1) {
+ StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
+ if (value_sp)
+ array_up->AddItem(value_sp);
+ else
+ break;
+
+ JSONParser::Token token = json_parser.GetToken(value);
+ if (token == JSONParser::Token::Comma) {
+ continue;
+ } else if (token == JSONParser::Token::ArrayEnd) {
+ return StructuredData::ObjectSP(array_up.release());
+ } else {
+ break;
+ }
+ }
+ return StructuredData::ObjectSP();
+}
+
+static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser) {
+ std::string value;
+ const JSONParser::Token token = json_parser.GetToken(value);
+ switch (token) {
+ case JSONParser::Token::ObjectStart:
+ return ParseJSONObject(json_parser);
+
+ case JSONParser::Token::ArrayStart:
+ return ParseJSONArray(json_parser);
+
+ case JSONParser::Token::Integer: {
+ uint64_t uval;
+ if (llvm::to_integer(value, uval, 0))
+ return std::make_shared<StructuredData::Integer>(uval);
+ } break;
+
+ case JSONParser::Token::Float: {
+ double val;
+ if (llvm::to_float(value, val))
+ return std::make_shared<StructuredData::Float>(val);
+ } break;
+
+ case JSONParser::Token::String:
+ return std::make_shared<StructuredData::String>(value);
+
+ case JSONParser::Token::True:
+ case JSONParser::Token::False:
+ return std::make_shared<StructuredData::Boolean>(token ==
+ JSONParser::Token::True);
+
+ case JSONParser::Token::Null:
+ return std::make_shared<StructuredData::Null>();
+
+ default:
+ break;
+ }
+ return StructuredData::ObjectSP();
+}
+
+StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) {
+ JSONParser json_parser(json_text.c_str());
+ StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser);
+ return object_sp;
+}
+
+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.size() == 0) {
+ return this->shared_from_this();
+ }
+ errno = 0;
+ uint64_t val = strtoul(match.second.str().c_str(), NULL, 10);
+ if (errno == 0) {
+ return this->GetAsArray()->GetItemAtIndex(val);
+ }
+ return ObjectSP();
+ }
+
+ return this->shared_from_this();
+}
+
+void StructuredData::Object::DumpToStdout(bool pretty_print) const {
+ StreamString stream;
+ Dump(stream, pretty_print);
+ llvm::outs() << stream.GetString();
+}
+
+void StructuredData::Array::Dump(Stream &s, bool pretty_print) const {
+ bool first = true;
+ s << "[";
+ if (pretty_print) {
+ s << "\n";
+ s.IndentMore();
+ }
+ for (const auto &item_sp : m_items) {
+ if (first) {
+ first = false;
+ } else {
+ s << ",";
+ if (pretty_print)
+ s << "\n";
+ }
+
+ if (pretty_print)
+ s.Indent();
+ item_sp->Dump(s, pretty_print);
+ }
+ if (pretty_print) {
+ s.IndentLess();
+ s.EOL();
+ s.Indent();
+ }
+ s << "]";
+}
+
+void StructuredData::Integer::Dump(Stream &s, bool pretty_print) const {
+ s.Printf("%" PRIu64, m_value);
+}
+
+void StructuredData::Float::Dump(Stream &s, bool pretty_print) const {
+ s.Printf("%lg", m_value);
+}
+
+void StructuredData::Boolean::Dump(Stream &s, bool pretty_print) const {
+ if (m_value == true)
+ s.PutCString("true");
+ else
+ s.PutCString("false");
+}
+
+void StructuredData::String::Dump(Stream &s, bool pretty_print) const {
+ std::string quoted;
+ const size_t strsize = m_value.size();
+ for (size_t i = 0; i < strsize; ++i) {
+ char ch = m_value[i];
+ if (ch == '"' || ch == '\\')
+ quoted.push_back('\\');
+ quoted.push_back(ch);
+ }
+ s.Printf("\"%s\"", quoted.c_str());
+}
+
+void StructuredData::Dictionary::Dump(Stream &s, bool pretty_print) const {
+ bool first = true;
+ s << "{";
+ if (pretty_print) {
+ s << "\n";
+ s.IndentMore();
+ }
+ for (const auto &pair : m_dict) {
+ if (first)
+ first = false;
+ else {
+ s << ",";
+ if (pretty_print)
+ s << "\n";
+ }
+ if (pretty_print)
+ s.Indent();
+ s << "\"" << pair.first.AsCString() << "\" : ";
+ pair.second->Dump(s, pretty_print);
+ }
+ if (pretty_print) {
+ s.IndentLess();
+ s.EOL();
+ s.Indent();
+ }
+ s << "}";
+}
+
+void StructuredData::Null::Dump(Stream &s, bool pretty_print) const {
+ s << "null";
+}
+
+void StructuredData::Generic::Dump(Stream &s, bool pretty_print) const {
+ s << "0x" << m_object;
+}
OpenPOWER on IntegriCloud