aboutsummaryrefslogtreecommitdiff
path: root/source/Core/StructuredData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Core/StructuredData.cpp')
-rw-r--r--source/Core/StructuredData.cpp429
1 files changed, 429 insertions, 0 deletions
diff --git a/source/Core/StructuredData.cpp b/source/Core/StructuredData.cpp
new file mode 100644
index 000000000000..3c43e41f3c94
--- /dev/null
+++ b/source/Core/StructuredData.cpp
@@ -0,0 +1,429 @@
+//===---------------------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>
+
+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::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";
+}