summaryrefslogtreecommitdiffstats
path: root/source/Core/StructuredData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Core/StructuredData.cpp')
-rw-r--r--source/Core/StructuredData.cpp343
1 files changed, 95 insertions, 248 deletions
diff --git a/source/Core/StructuredData.cpp b/source/Core/StructuredData.cpp
index a2c4409..efc104f 100644
--- a/source/Core/StructuredData.cpp
+++ b/source/Core/StructuredData.cpp
@@ -14,301 +14,148 @@
#include <inttypes.h>
#include "lldb/Core/StreamString.h"
+#include "lldb/Host/StringConvert.h"
+#include "lldb/Utility/JSON.h"
using namespace lldb_private;
-static StructuredData::ObjectSP read_json_object (const char **ch);
-static StructuredData::ObjectSP read_json_array (const char **ch);
+//----------------------------------------------------------------------
+// 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
-read_json_number (const char **ch)
+ParseJSONObject (JSONParser &json_parser)
{
- 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 == '}')
+ // 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)
{
- if (is_integer)
+ JSONParser::Token token = json_parser.GetToken(value);
+
+ if (token == JSONParser::Token::String)
{
- errno = 0;
- uint64_t val = strtoul (start_of_number, NULL, 10);
- if (errno == 0)
+ key.swap(value);
+ token = json_parser.GetToken(value);
+ if (token == JSONParser::Token::Colon)
{
- object_sp.reset(new StructuredData::Integer());
- object_sp->GetAsInteger()->SetValue (val);
+ StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
+ if (value_sp)
+ dict_up->AddItem(key, value_sp);
+ else
+ break;
}
}
- if (is_float)
+ else if (token == JSONParser::Token::ObjectEnd)
{
- 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 StructuredData::ObjectSP(dict_up.release());
}
- }
- return object_sp;
-}
-
-static std::string
-read_json_string (const char **ch)
-{
- std::string string;
- if (**ch == '"')
- {
- (*ch)++;
- while (**ch != '\0')
+ else if (token == JSONParser::Token::Comma)
{
- 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)++;
+ continue;
+ }
+ else
+ {
+ break;
}
}
- return string;
+ return StructuredData::ObjectSP();
}
static StructuredData::ObjectSP
-read_json_value (const char **ch)
+ParseJSONArray (JSONParser &json_parser)
{
- StructuredData::ObjectSP object_sp;
- while (isspace (**ch))
- (*ch)++;
+ // 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());
- if (**ch == '{')
- {
- object_sp = read_json_object (ch);
- }
- else if (**ch == '[')
+ std::string value;
+ std::string key;
+ while (1)
{
- 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)
+ 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)
{
- object_sp.reset(new StructuredData::Boolean());
- object_sp->GetAsBoolean()->SetValue(false);
- *ch += 5;
+ continue;
}
- else if (strncmp (*ch, "null", 4) == 0)
+ else if (token == JSONParser::Token::ArrayEnd)
{
- object_sp.reset(new StructuredData::Null());
- *ch += 4;
+ return StructuredData::ObjectSP(array_up.release());
}
else
{
- object_sp = read_json_number (ch);
+ break;
}
}
- return object_sp;
+ return StructuredData::ObjectSP();
}
static StructuredData::ObjectSP
-read_json_array (const char **ch)
+ParseJSONValue (JSONParser &json_parser)
{
- StructuredData::ObjectSP object_sp;
- if (**ch == '[')
+ std::string value;
+ const JSONParser::Token token = json_parser.GetToken(value);
+ switch (token)
{
- (*ch)++;
- while (isspace (**ch))
- (*ch)++;
+ case JSONParser::Token::ObjectStart:
+ return ParseJSONObject(json_parser);
- 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)
+ case JSONParser::Token::ArrayStart:
+ return ParseJSONArray(json_parser);
+
+ case JSONParser::Token::Integer:
{
- if (object_sp.get() == NULL)
- {
- object_sp.reset(new StructuredData::Array());
- }
- object_sp->GetAsArray()->Push (value_sp);
+ bool success = false;
+ uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
+ if (success)
+ return StructuredData::ObjectSP(new StructuredData::Integer(uval));
}
- 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;
-}
+ break;
-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 == ':')
+ case JSONParser::Token::Float:
{
- (*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);
- }
+ bool success = false;
+ double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
+ if (success)
+ return StructuredData::ObjectSP(new StructuredData::Float(val));
}
- 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)++;
- }
+ 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 object_sp;
-}
+ return StructuredData::ObjectSP();
+}
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 if (*c == '[')
- {
- object_sp = read_json_array (&c);
- }
- else
- {
- // We have bad characters here, this is likely an illegal JSON string.
- return object_sp;
- }
- }
- }
+ JSONParser json_parser(json_text.c_str());
+ StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser);
return object_sp;
}
@@ -395,7 +242,7 @@ StructuredData::Integer::Dump (Stream &s) const
void
StructuredData::Float::Dump (Stream &s) const
{
- s.Printf ("%lf", m_value);
+ s.Printf ("%lg", m_value);
}
void
OpenPOWER on IntegriCloud