forked from OSchip/llvm-project
306 lines
7.7 KiB
C++
306 lines
7.7 KiB
C++
//===---------------------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/Core/StructuredData.h"
|
|
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <inttypes.h>
|
|
|
|
#include "lldb/Core/StreamString.h"
|
|
#include "lldb/Host/StringConvert.h"
|
|
#include "lldb/Utility/JSON.h"
|
|
|
|
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);
|
|
|
|
static StructuredData::ObjectSP
|
|
ParseJSONObject (JSONParser &json_parser)
|
|
{
|
|
// The "JSONParser::Token::ObjectStart" token should have already been consumed
|
|
// by the time this function is called
|
|
std::unique_ptr<StructuredData::Dictionary> dict_up(new 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
|
|
std::unique_ptr<StructuredData::Array> array_up(new 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:
|
|
{
|
|
bool success = false;
|
|
uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
|
|
if (success)
|
|
return StructuredData::ObjectSP(new StructuredData::Integer(uval));
|
|
}
|
|
break;
|
|
|
|
case JSONParser::Token::Float:
|
|
{
|
|
bool success = false;
|
|
double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
|
|
if (success)
|
|
return StructuredData::ObjectSP(new StructuredData::Float(val));
|
|
}
|
|
break;
|
|
|
|
case JSONParser::Token::String:
|
|
return StructuredData::ObjectSP(new StructuredData::String(value));
|
|
|
|
case JSONParser::Token::True:
|
|
case JSONParser::Token::False:
|
|
return StructuredData::ObjectSP(new StructuredData::Boolean(token == JSONParser::Token::True));
|
|
|
|
case JSONParser::Token::Null:
|
|
return StructuredData::ObjectSP(new 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() == Type::eTypeDictionary)
|
|
{
|
|
std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
|
|
std::string key = match.first.str();
|
|
ObjectSP value = this->GetAsDictionary()->GetValueForKey (key.c_str());
|
|
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() == Type::eTypeArray)
|
|
{
|
|
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() const
|
|
{
|
|
StreamString stream;
|
|
Dump(stream);
|
|
printf("%s\n", stream.GetString().c_str());
|
|
}
|
|
|
|
void
|
|
StructuredData::Array::Dump(Stream &s) const
|
|
{
|
|
bool first = true;
|
|
s << "[\n";
|
|
s.IndentMore();
|
|
for (const auto &item_sp : m_items)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
s << ",\n";
|
|
|
|
s.Indent();
|
|
item_sp->Dump(s);
|
|
}
|
|
s.IndentLess();
|
|
s.EOL();
|
|
s.Indent();
|
|
s << "]";
|
|
}
|
|
|
|
void
|
|
StructuredData::Integer::Dump (Stream &s) const
|
|
{
|
|
s.Printf ("%" PRIu64, m_value);
|
|
}
|
|
|
|
|
|
void
|
|
StructuredData::Float::Dump (Stream &s) const
|
|
{
|
|
s.Printf ("%lg", m_value);
|
|
}
|
|
|
|
void
|
|
StructuredData::Boolean::Dump (Stream &s) const
|
|
{
|
|
if (m_value == true)
|
|
s.PutCString ("true");
|
|
else
|
|
s.PutCString ("false");
|
|
}
|
|
|
|
|
|
void
|
|
StructuredData::String::Dump (Stream &s) 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 == '"')
|
|
quoted.push_back ('\\');
|
|
quoted.push_back (ch);
|
|
}
|
|
s.Printf ("\"%s\"", quoted.c_str());
|
|
}
|
|
|
|
void
|
|
StructuredData::Dictionary::Dump (Stream &s) const
|
|
{
|
|
bool first = true;
|
|
s << "{\n";
|
|
s.IndentMore();
|
|
for (const auto &pair : m_dict)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
s << ",\n";
|
|
s.Indent();
|
|
s << "\"" << pair.first.AsCString() << "\" : ";
|
|
pair.second->Dump(s);
|
|
}
|
|
s.IndentLess();
|
|
s.EOL();
|
|
s.Indent();
|
|
s << "}";
|
|
}
|
|
|
|
void
|
|
StructuredData::Null::Dump (Stream &s) const
|
|
{
|
|
s << "null";
|
|
}
|
|
|
|
void
|
|
StructuredData::Generic::Dump(Stream &s) const
|
|
{
|
|
s << "0x" << m_object;
|
|
}
|