Files
clang-p2996/lldb/source/Core/StructuredData.cpp
Zachary Turner 0641ca1a2d Remove ScriptInterpreterObject.
This removes ScriptInterpreterObject from the codebase completely.
Places that used to rely on ScriptInterpreterObject now use
StructuredData::Object and its derived classes.  To support this,
a new type of StructuredData object is introduced, called
StructuredData::Generic, which stores a void*.  Internally within
the python library, StructuredPythonObject subclasses this
StructuredData::Generic class so that it can addref and decref
the python object on construction and destruction.

Additionally, all of the classes in PythonDataObjects.h such
as PythonList, PythonDictionary, etc now provide a method to
create an instance of the corresponding StructuredData type.  For
example, there is PythonDictionary::CreateStructuredDictionary.
To eliminate dependencies on PythonDataObjects for external
callers, all ScriptInterpreter methods now return only
StructuredData classes

The rest of the changes in this CL are focused on fixing up
users of PythonDataObjects classes to use the new StructuredData
classes.

llvm-svn: 232534
2015-03-17 20:04:04 +00:00

446 lines
11 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"
using namespace lldb_private;
static StructuredData::ObjectSP read_json_object (const char **ch);
static StructuredData::ObjectSP read_json_array (const char **ch);
static StructuredData::ObjectSP
read_json_number (const char **ch)
{
StructuredData::ObjectSP object_sp;
while (isspace (**ch))
(*ch)++;
const char *start_of_number = *ch;
bool is_integer = true;
bool is_float = false;
while (isdigit(**ch) || **ch == '-' || **ch == '.' || **ch == '+' || **ch == 'e' || **ch == 'E')
{
if (isdigit(**ch) == false && **ch != '-')
{
is_integer = false;
is_float = true;
}
(*ch)++;
}
while (isspace (**ch))
(*ch)++;
if (**ch == ',' || **ch == ']' || **ch == '}')
{
if (is_integer)
{
errno = 0;
uint64_t val = strtoul (start_of_number, NULL, 10);
if (errno == 0)
{
object_sp.reset(new StructuredData::Integer());
object_sp->GetAsInteger()->SetValue (val);
}
}
if (is_float)
{
char *end_of_number = NULL;
errno = 0;
double val = strtod (start_of_number, &end_of_number);
if (errno == 0 && end_of_number != start_of_number && end_of_number != NULL)
{
object_sp.reset(new StructuredData::Float());
object_sp->GetAsFloat()->SetValue (val);
}
}
}
return object_sp;
}
static std::string
read_json_string (const char **ch)
{
std::string string;
if (**ch == '"')
{
(*ch)++;
while (**ch != '\0')
{
if (**ch == '"')
{
(*ch)++;
while (isspace (**ch))
(*ch)++;
break;
}
else if (**ch == '\\')
{
switch (**ch)
{
case '"':
string.push_back('"');
*ch += 2;
break;
case '\\':
string.push_back('\\');
*ch += 2;
break;
case '/':
string.push_back('/');
*ch += 2;
break;
case 'b':
string.push_back('\b');
*ch += 2;
break;
case 'f':
string.push_back('\f');
*ch += 2;
break;
case 'n':
string.push_back('\n');
*ch += 2;
break;
case 'r':
string.push_back('\r');
*ch += 2;
break;
case 't':
string.push_back('\t');
*ch += 2;
break;
case 'u':
// FIXME handle four-hex-digits
*ch += 10;
break;
default:
*ch += 1;
}
}
else
{
string.push_back (**ch);
}
(*ch)++;
}
}
return string;
}
static StructuredData::ObjectSP
read_json_value (const char **ch)
{
StructuredData::ObjectSP object_sp;
while (isspace (**ch))
(*ch)++;
if (**ch == '{')
{
object_sp = read_json_object (ch);
}
else if (**ch == '[')
{
object_sp = read_json_array (ch);
}
else if (**ch == '"')
{
std::string string = read_json_string (ch);
object_sp.reset(new StructuredData::String());
object_sp->GetAsString()->SetValue(string);
}
else
{
if (strncmp (*ch, "true", 4) == 0)
{
object_sp.reset(new StructuredData::Boolean());
object_sp->GetAsBoolean()->SetValue(true);
*ch += 4;
}
else if (strncmp (*ch, "false", 5) == 0)
{
object_sp.reset(new StructuredData::Boolean());
object_sp->GetAsBoolean()->SetValue(false);
*ch += 5;
}
else if (strncmp (*ch, "null", 4) == 0)
{
object_sp.reset(new StructuredData::Null());
*ch += 4;
}
else
{
object_sp = read_json_number (ch);
}
}
return object_sp;
}
static StructuredData::ObjectSP
read_json_array (const char **ch)
{
StructuredData::ObjectSP object_sp;
if (**ch == '[')
{
(*ch)++;
while (isspace (**ch))
(*ch)++;
bool first_value = true;
while (**ch != '\0' && (first_value || **ch == ','))
{
if (**ch == ',')
(*ch)++;
first_value = false;
while (isspace (**ch))
(*ch)++;
lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
if (value_sp)
{
if (object_sp.get() == NULL)
{
object_sp.reset(new StructuredData::Array());
}
object_sp->GetAsArray()->Push (value_sp);
}
while (isspace (**ch))
(*ch)++;
}
if (**ch == ']')
{
// FIXME should throw an error if we don't see a } to close out the JSON object
(*ch)++;
while (isspace (**ch))
(*ch)++;
}
}
return object_sp;
}
static StructuredData::ObjectSP
read_json_object (const char **ch)
{
StructuredData::ObjectSP object_sp;
if (**ch == '{')
{
(*ch)++;
while (isspace (**ch))
(*ch)++;
bool first_pair = true;
while (**ch != '\0' && (first_pair || **ch == ','))
{
first_pair = false;
if (**ch == ',')
(*ch)++;
while (isspace (**ch))
(*ch)++;
if (**ch != '"')
break;
std::string key_string = read_json_string (ch);
while (isspace (**ch))
(*ch)++;
if (key_string.size() > 0 && **ch == ':')
{
(*ch)++;
while (isspace (**ch))
(*ch)++;
lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
if (value_sp.get())
{
if (object_sp.get() == NULL)
{
object_sp.reset(new StructuredData::Dictionary());
}
object_sp->GetAsDictionary()->AddItem (key_string.c_str(), value_sp);
}
}
while (isspace (**ch))
(*ch)++;
}
if (**ch == '}')
{
// FIXME should throw an error if we don't see a } to close out the JSON object
(*ch)++;
while (isspace (**ch))
(*ch)++;
}
}
return object_sp;
}
StructuredData::ObjectSP
StructuredData::ParseJSON (std::string json_text)
{
StructuredData::ObjectSP object_sp;
const size_t json_text_size = json_text.size();
if (json_text_size > 0)
{
const char *start_of_json_text = json_text.c_str();
const char *c = json_text.c_str();
while (*c != '\0' &&
static_cast<size_t>(c - start_of_json_text) <= json_text_size)
{
while (isspace (*c) &&
static_cast<size_t>(c - start_of_json_text) < json_text_size)
c++;
if (*c == '{')
{
object_sp = read_json_object (&c);
}
else
{
// We have bad characters here, this is likely an illegal JSON string.
return object_sp;
}
}
}
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", stream.GetString().c_str());
}
void
StructuredData::Array::Dump(Stream &s) const
{
s << "[";
const size_t arrsize = m_items.size();
for (size_t i = 0; i < arrsize; ++i)
{
m_items[i]->Dump(s);
if (i + 1 < arrsize)
s << ",";
}
s << "]";
}
void
StructuredData::Integer::Dump (Stream &s) const
{
s.Printf ("%" PRIu64, m_value);
}
void
StructuredData::Float::Dump (Stream &s) const
{
s.Printf ("%lf", 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 have_printed_one_elem = false;
s << "{";
for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter)
{
if (have_printed_one_elem == false)
{
have_printed_one_elem = true;
}
else
{
s << ",";
}
s << "\"" << iter->first.AsCString() << "\":";
iter->second->Dump(s);
}
s << "}";
}
void
StructuredData::Null::Dump (Stream &s) const
{
s << "null";
}
void
StructuredData::Generic::Dump(Stream &s) const
{
s << "0x" << m_object;
}