summaryrefslogtreecommitdiffstats
path: root/source/Utility
diff options
context:
space:
mode:
Diffstat (limited to 'source/Utility')
-rw-r--r--source/Utility/JSON.cpp470
-rw-r--r--source/Utility/StringExtractor.cpp11
-rw-r--r--source/Utility/StringExtractor.h164
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp8
-rw-r--r--source/Utility/StringExtractorGDBRemote.h4
5 files changed, 472 insertions, 185 deletions
diff --git a/source/Utility/JSON.cpp b/source/Utility/JSON.cpp
index 0ba8cf4..1e16a5a 100644
--- a/source/Utility/JSON.cpp
+++ b/source/Utility/JSON.cpp
@@ -9,6 +9,10 @@
#include "lldb/Utility/JSON.h"
+#include <limits.h>
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/StringConvert.h"
+
using namespace lldb_private;
std::string
@@ -33,20 +37,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 +61,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 (uint64_t i) :
+ JSONValue(JSONValue::Kind::Number),
+ m_is_integer(true),
+ m_data(i),
+ m_double(0.0)
{
}
-JSONNumber::JSONNumber (int64_t i) :
-JSONValue(JSONValue::Kind::Number),
-m_data(i)
+
+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 +106,7 @@ JSONTrue::Write(Stream& s)
}
JSONFalse::JSONFalse () :
-JSONValue(JSONValue::Kind::False)
+ JSONValue(JSONValue::Kind::False)
{
}
@@ -97,7 +117,7 @@ JSONFalse::Write(Stream& s)
}
JSONNull::JSONNull () :
-JSONValue(JSONValue::Kind::Null)
+ JSONValue(JSONValue::Kind::Null)
{
}
@@ -108,7 +128,7 @@ JSONNull::Write(Stream& s)
}
JSONObject::JSONObject () :
-JSONValue(JSONValue::Kind::Object)
+ JSONValue(JSONValue::Kind::Object)
{
}
@@ -153,7 +173,7 @@ JSONObject::GetObject (const std::string& key)
}
JSONArray::JSONArray () :
-JSONValue(JSONValue::Kind::Array)
+ JSONValue(JSONValue::Kind::Array)
{
}
@@ -215,3 +235,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/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
index e82c83d..6302c03 100644
--- a/source/Utility/StringExtractor.cpp
+++ b/source/Utility/StringExtractor.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "Utility/StringExtractor.h"
+#include "lldb/Utility/StringExtractor.h"
// C Includes
#include <stdlib.h>
@@ -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/source/Utility/StringExtractor.h b/source/Utility/StringExtractor.h
deleted file mode 100644
index 49dfe99..0000000
--- a/source/Utility/StringExtractor.h
+++ /dev/null
@@ -1,164 +0,0 @@
-//===-- StringExtractor.h ---------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef utility_StringExtractor_h_
-#define utility_StringExtractor_h_
-
-// C Includes
-// C++ Includes
-#include <string>
-#include <stdint.h>
-
-// Other libraries and framework includes
-// Project includes
-
-class StringExtractor
-{
-public:
-
- enum {
- BigEndian = 0,
- LittleEndian = 1
- };
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- StringExtractor();
- StringExtractor(const char *packet_cstr);
- StringExtractor(const StringExtractor& rhs);
- virtual ~StringExtractor();
-
- //------------------------------------------------------------------
- // Operators
- //------------------------------------------------------------------
- const StringExtractor&
- operator=(const StringExtractor& rhs);
-
- // Returns true if the file position is still valid for the data
- // contained in this string extractor object.
- bool
- IsGood() const
- {
- return m_index != UINT64_MAX;
- }
-
- uint64_t
- GetFilePos () const
- {
- return m_index;
- }
-
- void
- SetFilePos (uint32_t idx)
- {
- m_index = idx;
- }
-
- void
- Clear ()
- {
- m_packet.clear();
- m_index = 0;
- }
-
- std::string &
- GetStringRef ()
- {
- return m_packet;
- }
-
- const std::string &
- GetStringRef () const
- {
- return m_packet;
- }
-
- bool
- Empty()
- {
- return m_packet.empty();
- }
-
- size_t
- GetBytesLeft ()
- {
- if (m_index < m_packet.size())
- return m_packet.size() - m_index;
- return 0;
- }
-
- char
- GetChar (char fail_value = '\0');
-
- int
- DecodeHexU8();
-
- uint8_t
- GetHexU8 (uint8_t fail_value = 0, bool set_eof_on_fail = true);
-
- bool
- GetNameColonValue (std::string &name, std::string &value);
-
- int32_t
- GetS32 (int32_t fail_value, int base = 0);
-
- uint32_t
- GetU32 (uint32_t fail_value, int base = 0);
-
- int64_t
- GetS64 (int64_t fail_value, int base = 0);
-
- uint64_t
- GetU64 (uint64_t fail_value, int base = 0);
-
- uint32_t
- GetHexMaxU32 (bool little_endian, uint32_t fail_value);
-
- uint64_t
- GetHexMaxU64 (bool little_endian, uint64_t fail_value);
-
- size_t
- GetHexBytes (void *dst, size_t dst_len, uint8_t fail_fill_value);
-
- size_t
- GetHexBytesAvail (void *dst, size_t dst_len);
-
- uint64_t
- GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value);
-
- size_t
- GetHexByteString (std::string &str);
-
- size_t
- GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length);
-
- size_t
- GetHexByteStringTerminatedBy (std::string &str,
- char terminator);
-
- const char *
- Peek ()
- {
- if (m_index < m_packet.size())
- return m_packet.c_str() + m_index;
- return nullptr;
- }
-
-protected:
- //------------------------------------------------------------------
- // For StringExtractor only
- //------------------------------------------------------------------
- std::string m_packet; // The string in which to extract data.
- uint64_t m_index; // When extracting data from a packet, this index
- // will march along as things get extracted. If set
- // to UINT64_MAX the end of the packet data was
- // reached when decoding information
-};
-
-#endif // utility_StringExtractor_h_
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index aeceaa0..17ee0b6 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -82,7 +82,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
case 'A':
return eServerPacketType_A;
-
+
case 'Q':
switch (packet_cstr[1])
@@ -122,7 +122,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
break;
}
break;
-
+
case 'q':
switch (packet_cstr[1])
{
@@ -219,6 +219,10 @@ StringExtractorGDBRemote::GetServerPacketType () const
break;
}
break;
+
+ case 'j':
+ if (PACKET_MATCHES("jSignalInfo")) return eServerPacketType_jSignalsInfo;
+
case 'v':
if (PACKET_STARTS_WITH("vFile:"))
{
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
index beb07e5..475b5a8 100644
--- a/source/Utility/StringExtractorGDBRemote.h
+++ b/source/Utility/StringExtractorGDBRemote.h
@@ -15,7 +15,7 @@
#include <string>
// Other libraries and framework includes
// Project includes
-#include "Utility/StringExtractor.h"
+#include "lldb/Utility/StringExtractor.h"
class StringExtractorGDBRemote : public StringExtractor
{
@@ -118,6 +118,8 @@ public:
eServerPacketType_qWatchpointSupportInfoSupported,
eServerPacketType_qXfer_auxv_read,
+ eServerPacketType_jSignalsInfo,
+
eServerPacketType_vAttach,
eServerPacketType_vAttachWait,
eServerPacketType_vAttachOrWait,
OpenPOWER on IntegriCloud