diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/Core/StructuredData.cpp | 343 | ||||
-rw-r--r-- | lldb/source/Host/common/StringConvert.cpp | 142 | ||||
-rw-r--r-- | lldb/source/Utility/JSON.cpp | 468 | ||||
-rw-r--r-- | lldb/source/Utility/StringExtractor.cpp | 9 | ||||
-rw-r--r-- | lldb/source/Utility/StringExtractor.h | 12 |
5 files changed, 650 insertions, 324 deletions
diff --git a/lldb/source/Core/StructuredData.cpp b/lldb/source/Core/StructuredData.cpp index a2c440948af..efc104f1f3e 100644 --- a/lldb/source/Core/StructuredData.cpp +++ b/lldb/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 diff --git a/lldb/source/Host/common/StringConvert.cpp b/lldb/source/Host/common/StringConvert.cpp index 0a8e75f4b87..c4ff67515d4 100644 --- a/lldb/source/Host/common/StringConvert.cpp +++ b/lldb/source/Host/common/StringConvert.cpp @@ -15,79 +15,103 @@ // Project includes #include "lldb/Host/StringConvert.h" -namespace lldb_private { - -namespace StringConvert { - -int32_t -ToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr) +namespace lldb_private { - if (s && s[0]) + namespace StringConvert { - char *end = nullptr; - const long sval = ::strtol (s, &end, base); - if (*end == '\0') + + int32_t + ToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr) { + if (s && s[0]) + { + char *end = nullptr; + const long sval = ::strtol (s, &end, base); + if (*end == '\0') + { + if (success_ptr) + *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN)); + return (int32_t)sval; // All characters were used, return the result + } + } if (success_ptr) - *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN)); - return (int32_t)sval; // All characters were used, return the result + *success_ptr = false; + return fail_value; } - } - if (success_ptr) *success_ptr = false; - return fail_value; -} -uint32_t -ToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr) -{ - if (s && s[0]) - { - char *end = nullptr; - const unsigned long uval = ::strtoul (s, &end, base); - if (*end == '\0') + uint32_t + ToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr) { + if (s && s[0]) + { + char *end = nullptr; + const unsigned long uval = ::strtoul (s, &end, base); + if (*end == '\0') + { + if (success_ptr) + *success_ptr = (uval <= UINT32_MAX); + return (uint32_t)uval; // All characters were used, return the result + } + } if (success_ptr) - *success_ptr = (uval <= UINT32_MAX); - return (uint32_t)uval; // All characters were used, return the result + *success_ptr = false; + return fail_value; } - } - if (success_ptr) *success_ptr = false; - return fail_value; -} -int64_t -ToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr) -{ - if (s && s[0]) - { - char *end = nullptr; - int64_t uval = ::strtoll (s, &end, base); - if (*end == '\0') + int64_t + ToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr) { - if (success_ptr) *success_ptr = true; - return uval; // All characters were used, return the result + if (s && s[0]) + { + char *end = nullptr; + int64_t uval = ::strtoll (s, &end, base); + if (*end == '\0') + { + if (success_ptr) + *success_ptr = true; + return uval; // All characters were used, return the result + } + } + if (success_ptr) + *success_ptr = false; + return fail_value; } - } - if (success_ptr) *success_ptr = false; - return fail_value; -} -uint64_t -ToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr) -{ - if (s && s[0]) - { - char *end = nullptr; - uint64_t uval = ::strtoull (s, &end, base); - if (*end == '\0') + uint64_t + ToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr) { - if (success_ptr) *success_ptr = true; - return uval; // All characters were used, return the result + if (s && s[0]) + { + char *end = nullptr; + uint64_t uval = ::strtoull (s, &end, base); + if (*end == '\0') + { + if (success_ptr) + *success_ptr = true; + return uval; // All characters were used, return the result + } + } + if (success_ptr) *success_ptr = false; + return fail_value; } - } - if (success_ptr) *success_ptr = false; - return fail_value; -} -} + double + ToDouble (const char *s, double fail_value, bool *success_ptr) + { + if (s && s[0]) + { + char *end = nullptr; + double val = strtod (s, &end); + if (*end == '\0') + { + if (success_ptr) + *success_ptr = true; + return val; // All characters were used, return the result + } + } + if (success_ptr) + *success_ptr = false; + return fail_value; + } + } } diff --git a/lldb/source/Utility/JSON.cpp b/lldb/source/Utility/JSON.cpp index 0ba8cf4399c..eaf224d555f 100644 --- a/lldb/source/Utility/JSON.cpp +++ b/lldb/source/Utility/JSON.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Utility/JSON.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/StringConvert.h" using namespace lldb_private; @@ -33,20 +35,20 @@ JSONString::json_string_quote_metachars (const std::string &s) } JSONString::JSONString () : -JSONValue(JSONValue::Kind::String), -m_data() + JSONValue(JSONValue::Kind::String), + m_data() { } JSONString::JSONString (const char* s) : -JSONValue(JSONValue::Kind::String), -m_data(s ? s : "") + JSONValue(JSONValue::Kind::String), + m_data(s ? s : "") { } JSONString::JSONString (const std::string& s) : -JSONValue(JSONValue::Kind::String), -m_data(s) + JSONValue(JSONValue::Kind::String), + m_data(s) { } @@ -57,25 +59,41 @@ JSONString::Write (Stream& s) } JSONNumber::JSONNumber () : -JSONValue(JSONValue::Kind::Number), -m_data(0) + JSONValue(JSONValue::Kind::Number), + m_is_integer(true), + m_data(0), + m_double(0.0) { } -JSONNumber::JSONNumber (int64_t i) : -JSONValue(JSONValue::Kind::Number), -m_data(i) +JSONNumber::JSONNumber (uint64_t i) : + JSONValue(JSONValue::Kind::Number), + m_is_integer(true), + m_data(i), + m_double(0.0) +{ +} + + +JSONNumber::JSONNumber (double d) : + JSONValue(JSONValue::Kind::Number), + m_is_integer(false), + m_data(0), + m_double(d) { } void JSONNumber::Write (Stream& s) { - s.Printf("%" PRId64, m_data); + if (m_is_integer) + s.Printf("%" PRIu64, m_data); + else + s.Printf("%g", m_double); } JSONTrue::JSONTrue () : -JSONValue(JSONValue::Kind::True) + JSONValue(JSONValue::Kind::True) { } @@ -86,7 +104,7 @@ JSONTrue::Write(Stream& s) } JSONFalse::JSONFalse () : -JSONValue(JSONValue::Kind::False) + JSONValue(JSONValue::Kind::False) { } @@ -97,7 +115,7 @@ JSONFalse::Write(Stream& s) } JSONNull::JSONNull () : -JSONValue(JSONValue::Kind::Null) + JSONValue(JSONValue::Kind::Null) { } @@ -108,7 +126,7 @@ JSONNull::Write(Stream& s) } JSONObject::JSONObject () : -JSONValue(JSONValue::Kind::Object) + JSONValue(JSONValue::Kind::Object) { } @@ -153,7 +171,7 @@ JSONObject::GetObject (const std::string& key) } JSONArray::JSONArray () : -JSONValue(JSONValue::Kind::Array) + JSONValue(JSONValue::Kind::Array) { } @@ -215,3 +233,419 @@ JSONArray::GetNumElements () { return m_elements.size(); } + + +JSONParser::JSONParser (const char *cstr) : + StringExtractor(cstr) +{ +} + +JSONParser::Token +JSONParser::GetToken (std::string &value) +{ + StreamString error; + + value.clear(); + SkipSpaces (); + const uint64_t start_index = m_index; + const char ch = GetChar(); + switch (ch) + { + case '{': return Token::ObjectStart; + case '}': return Token::ObjectEnd; + case '[': return Token::ArrayStart; + case ']': return Token::ArrayEnd; + case ',': return Token::Comma; + case ':': return Token::Colon; + case '\0': return Token::EndOfFile; + case 't': + if (GetChar() == 'r') + if (GetChar() == 'u') + if (GetChar() == 'e') + return Token::True; + break; + + case 'f': + if (GetChar() == 'a') + if (GetChar() == 'l') + if (GetChar() == 's') + if (GetChar() == 'e') + return Token::False; + break; + + case 'n': + if (GetChar() == 'u') + if (GetChar() == 'l') + if (GetChar() == 'l') + return Token::Null; + break; + + case '"': + { + while (1) + { + bool was_escaped = false; + int escaped_ch = GetEscapedChar(was_escaped); + if (escaped_ch == -1) + { + error.Printf("error: an error occurred getting a character from offset %" PRIu64, start_index); + value = std::move(error.GetString()); + return Token::Error; + + } + else + { + const bool is_end_quote = escaped_ch == '"'; + const bool is_null = escaped_ch == 0; + if (was_escaped || (!is_end_quote && !is_null)) + { + if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) + { + value.append(1, (char)escaped_ch); + } + else + { + error.Printf("error: wide character support is needed for unicode character 0x%4.4x at offset %" PRIu64, escaped_ch, start_index); + value = std::move(error.GetString()); + return Token::Error; + } + } + else if (is_end_quote) + { + return Token::String; + } + else if (is_null) + { + value = "error: missing end quote for string"; + return Token::Error; + } + } + } + } + break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + bool done = false; + bool got_decimal_point = false; + uint64_t exp_index = 0; + bool got_int_digits = (ch >= '0') && (ch <= '9'); + bool got_frac_digits = false; + bool got_exp_digits = false; + while (!done) + { + const char next_ch = PeekChar(); + switch (next_ch) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (exp_index != 0) + { + got_exp_digits = true; + } + else if (got_decimal_point) + { + got_frac_digits = true; + } + else + { + got_int_digits = true; + } + ++m_index; // Skip this character + break; + + case '.': + if (got_decimal_point) + { + error.Printf("error: extra decimal point found at offset %" PRIu64, start_index); + value = std::move(error.GetString()); + return Token::Error; + } + else + { + got_decimal_point = true; + ++m_index; // Skip this character + } + break; + + case 'e': + case 'E': + if (exp_index != 0) + { + error.Printf("error: extra expenent character found at offset %" PRIu64, start_index); + value = std::move(error.GetString()); + return Token::Error; + } + else + { + exp_index = m_index; + ++m_index; // Skip this character + } + break; + + case '+': + case '-': + // The '+' and '-' can only come after an exponent character... + if (exp_index == m_index - 1) + { + ++m_index; // Skip the exponent sign character + } + else + { + error.Printf("error: unexpected %c character at offset %" PRIu64, next_ch, start_index); + value = std::move(error.GetString()); + return Token::Error; + } + + default: + done = true; + break; + } + } + + if (m_index > start_index) + { + value = m_packet.substr(start_index, m_index - start_index); + if (got_decimal_point) + { + if (exp_index != 0) + { + // We have an exponent, make sure we got exponent digits + if (got_exp_digits) + { + return Token::Float; + } + else + { + error.Printf("error: got exponent character but no exponent digits at offset in float value \"%s\"", value.c_str()); + value = std::move(error.GetString()); + return Token::Error; + } + } + else + { + // No exponent, but we need at least one decimal after the decimal point + if (got_frac_digits) + { + return Token::Float; + } + else + { + error.Printf("error: no digits after decimal point \"%s\"", value.c_str()); + value = std::move(error.GetString()); + return Token::Error; + } + } + } + else + { + // No decimal point + if (got_int_digits) + { + // We need at least some integer digits to make an integer + return Token::Integer; + } + else + { + error.Printf("error: no digits negate sign \"%s\"", value.c_str()); + value = std::move(error.GetString()); + return Token::Error; + } + } + } + else + { + error.Printf("error: invalid number found at offset %" PRIu64, start_index); + value = std::move(error.GetString()); + return Token::Error; + } + } + break; + default: + break; + } + error.Printf("error: failed to parse token at offset %" PRIu64 " (around character '%c')", start_index, ch); + value = std::move(error.GetString()); + return Token::Error; +} + +int +JSONParser::GetEscapedChar(bool &was_escaped) +{ + was_escaped = false; + const char ch = GetChar(); + if (ch == '\\') + { + was_escaped = true; + const char ch2 = GetChar(); + switch (ch2) + { + case '"': + case '\\': + case '/': + default: + break; + + case 'b': return '\b'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'u': + { + const int hi_byte = DecodeHexU8(); + const int lo_byte = DecodeHexU8(); + if (hi_byte >=0 && lo_byte >= 0) + return hi_byte << 8 | lo_byte; + return -1; + } + break; + } + return ch2; + } + return ch; +} + +JSONValue::SP +JSONParser::ParseJSONObject () +{ + // The "JSONParser::Token::ObjectStart" token should have already been consumed + // by the time this function is called + std::unique_ptr<JSONObject> dict_up(new JSONObject()); + + std::string value; + std::string key; + while (1) + { + JSONParser::Token token = GetToken(value); + + if (token == JSONParser::Token::String) + { + key.swap(value); + token = GetToken(value); + if (token == JSONParser::Token::Colon) + { + JSONValue::SP value_sp = ParseJSONValue(); + if (value_sp) + dict_up->SetObject(key, value_sp); + else + break; + } + } + else if (token == JSONParser::Token::ObjectEnd) + { + return JSONValue::SP(dict_up.release()); + } + else if (token == JSONParser::Token::Comma) + { + continue; + } + else + { + break; + } + } + return JSONValue::SP(); +} + +JSONValue::SP +JSONParser::ParseJSONArray () +{ + // The "JSONParser::Token::ObjectStart" token should have already been consumed + // by the time this function is called + std::unique_ptr<JSONArray> array_up(new JSONArray()); + + std::string value; + std::string key; + while (1) + { + JSONValue::SP value_sp = ParseJSONValue(); + if (value_sp) + array_up->AppendObject(value_sp); + else + break; + + JSONParser::Token token = GetToken(value); + if (token == JSONParser::Token::Comma) + { + continue; + } + else if (token == JSONParser::Token::ArrayEnd) + { + return JSONValue::SP(array_up.release()); + } + else + { + break; + } + } + return JSONValue::SP(); +} + +JSONValue::SP +JSONParser::ParseJSONValue () +{ + std::string value; + const JSONParser::Token token = GetToken(value); + switch (token) + { + case JSONParser::Token::ObjectStart: + return ParseJSONObject(); + + case JSONParser::Token::ArrayStart: + return ParseJSONArray(); + + case JSONParser::Token::Integer: + { + bool success = false; + uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success); + if (success) + return JSONValue::SP(new JSONNumber(uval)); + } + break; + + case JSONParser::Token::Float: + { + bool success = false; + double val = StringConvert::ToDouble(value.c_str(), 0.0, &success); + if (success) + return JSONValue::SP(new JSONNumber(val)); + } + break; + + case JSONParser::Token::String: + return JSONValue::SP(new JSONString(value)); + + case JSONParser::Token::True: + return JSONValue::SP(new JSONTrue()); + + case JSONParser::Token::False: + return JSONValue::SP(new JSONFalse()); + + case JSONParser::Token::Null: + return JSONValue::SP(new JSONNull()); + + default: + break; + } + return JSONValue::SP(); + +} diff --git a/lldb/source/Utility/StringExtractor.cpp b/lldb/source/Utility/StringExtractor.cpp index e82c83dfd09..bde5e1961d8 100644 --- a/lldb/source/Utility/StringExtractor.cpp +++ b/lldb/source/Utility/StringExtractor.cpp @@ -476,3 +476,12 @@ StringExtractor::GetNameColonValue (std::string &name, std::string &value) m_index = UINT64_MAX; return false; } + +void +StringExtractor::SkipSpaces () +{ + const size_t n = m_packet.size(); + while (m_index < n && isspace(m_packet[m_index])) + ++m_index; +} + diff --git a/lldb/source/Utility/StringExtractor.h b/lldb/source/Utility/StringExtractor.h index 49dfe99bd35..0f2dbb166be 100644 --- a/lldb/source/Utility/StringExtractor.h +++ b/lldb/source/Utility/StringExtractor.h @@ -67,6 +67,9 @@ public: m_index = 0; } + void + SkipSpaces (); + std::string & GetStringRef () { @@ -96,6 +99,15 @@ public: char GetChar (char fail_value = '\0'); + char + PeekChar (char fail_value = '\0') + { + const char *cstr = Peek(); + if (cstr) + return cstr[0]; + return fail_value; + } + int DecodeHexU8(); |