mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:31:50 +00:00
[VM] Extract simple JSON writer out of VM service-specific JSONStream
The purpose of this refactoring is to provide a convenient way to write JSON independently of VM service, which is excluded in PRODUCT build mode. Change-Id: I55700d9ead6ef9269a98714d8178f1edb35435cb Reviewed-on: https://dart-review.googlesource.com/18502 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
9ac19f0122
commit
172786b906
|
@ -22,32 +22,10 @@ namespace dart {
|
|||
|
||||
#ifndef PRODUCT
|
||||
|
||||
class MaybeOnStackBuffer {
|
||||
public:
|
||||
explicit MaybeOnStackBuffer(intptr_t size) {
|
||||
if (size > kOnStackBufferCapacity) {
|
||||
p_ = reinterpret_cast<char*>(malloc(size));
|
||||
} else {
|
||||
p_ = &buffer_[0];
|
||||
}
|
||||
}
|
||||
~MaybeOnStackBuffer() {
|
||||
if (p_ != &buffer_[0]) free(p_);
|
||||
}
|
||||
|
||||
char* p() { return p_; }
|
||||
|
||||
private:
|
||||
static const intptr_t kOnStackBufferCapacity = 4096;
|
||||
char* p_;
|
||||
char buffer_[kOnStackBufferCapacity];
|
||||
};
|
||||
|
||||
DECLARE_FLAG(bool, trace_service);
|
||||
|
||||
JSONStream::JSONStream(intptr_t buf_size)
|
||||
: open_objects_(0),
|
||||
buffer_(buf_size),
|
||||
: writer_(buf_size),
|
||||
default_id_zone_(),
|
||||
id_zone_(&default_id_zone_),
|
||||
reply_port_(ILLEGAL_PORT),
|
||||
|
@ -68,8 +46,6 @@ JSONStream::JSONStream(intptr_t buf_size)
|
|||
default_id_zone_.Init(ring, ObjectIdRing::kAllocateId);
|
||||
}
|
||||
|
||||
JSONStream::~JSONStream() {}
|
||||
|
||||
void JSONStream::Setup(Zone* zone,
|
||||
Dart_Port reply_port,
|
||||
const Instance& seq,
|
||||
|
@ -114,12 +90,12 @@ void JSONStream::Setup(Zone* zone,
|
|||
"request %s\n",
|
||||
Dart::UptimeMillis(), main_port, isolate_name, method_);
|
||||
}
|
||||
buffer_.Printf("{\"jsonrpc\":\"2.0\", \"result\":");
|
||||
buffer()->Printf("{\"jsonrpc\":\"2.0\", \"result\":");
|
||||
}
|
||||
|
||||
void JSONStream::SetupError() {
|
||||
buffer_.Clear();
|
||||
buffer_.Printf("{\"jsonrpc\":\"2.0\", \"error\":");
|
||||
Clear();
|
||||
buffer()->Printf("{\"jsonrpc\":\"2.0\", \"error\":");
|
||||
}
|
||||
|
||||
static const char* GetJSONRpcErrorMessage(intptr_t code) {
|
||||
|
@ -228,7 +204,7 @@ void JSONStream::PostReply() {
|
|||
} else if (seq_->IsNull()) {
|
||||
if (port == ILLEGAL_PORT) {
|
||||
// This path is only used in tests.
|
||||
buffer_.AddChar('}'); // Finish our message.
|
||||
buffer()->AddChar('}'); // Finish our message.
|
||||
char* cstr;
|
||||
intptr_t length;
|
||||
Steal(&cstr, &length);
|
||||
|
@ -241,7 +217,7 @@ void JSONStream::PostReply() {
|
|||
}
|
||||
ASSERT(port != ILLEGAL_PORT);
|
||||
|
||||
buffer_.AddChar('}'); // Finish our message.
|
||||
buffer()->AddChar('}'); // Finish our message.
|
||||
char* cstr;
|
||||
intptr_t length;
|
||||
Steal(&cstr, &length);
|
||||
|
@ -325,176 +301,11 @@ void JSONStream::ComputeOffsetAndCount(intptr_t length,
|
|||
*count = remaining;
|
||||
}
|
||||
}
|
||||
|
||||
void JSONStream::AppendSerializedObject(const char* serialized_object) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddString(serialized_object);
|
||||
}
|
||||
|
||||
void JSONStream::AppendSerializedObject(const uint8_t* buffer,
|
||||
intptr_t buffer_length) {
|
||||
buffer_.AddRaw(buffer, buffer_length);
|
||||
}
|
||||
|
||||
void JSONStream::AppendSerializedObject(const char* property_name,
|
||||
const char* serialized_object) {
|
||||
PrintCommaIfNeeded();
|
||||
PrintPropertyName(property_name);
|
||||
buffer_.AddString(serialized_object);
|
||||
}
|
||||
|
||||
void JSONStream::Clear() {
|
||||
buffer_.Clear();
|
||||
open_objects_ = 0;
|
||||
}
|
||||
|
||||
void JSONStream::OpenObject(const char* property_name) {
|
||||
PrintCommaIfNeeded();
|
||||
open_objects_++;
|
||||
if (property_name != NULL) {
|
||||
PrintPropertyName(property_name);
|
||||
}
|
||||
buffer_.AddChar('{');
|
||||
}
|
||||
|
||||
void JSONStream::UncloseObject() {
|
||||
intptr_t len = buffer_.length();
|
||||
ASSERT(len > 0);
|
||||
ASSERT(buffer_.buf()[len - 1] == '}');
|
||||
open_objects_++;
|
||||
buffer_.set_length(len - 1);
|
||||
}
|
||||
|
||||
void JSONStream::CloseObject() {
|
||||
ASSERT(open_objects_ > 0);
|
||||
open_objects_--;
|
||||
buffer_.AddChar('}');
|
||||
}
|
||||
|
||||
void JSONStream::OpenArray(const char* property_name) {
|
||||
PrintCommaIfNeeded();
|
||||
if (property_name != NULL) {
|
||||
PrintPropertyName(property_name);
|
||||
}
|
||||
open_objects_++;
|
||||
buffer_.AddChar('[');
|
||||
}
|
||||
|
||||
void JSONStream::CloseArray() {
|
||||
ASSERT(open_objects_ > 0);
|
||||
open_objects_--;
|
||||
buffer_.AddChar(']');
|
||||
}
|
||||
|
||||
void JSONStream::PrintValueNull() {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("null");
|
||||
}
|
||||
|
||||
void JSONStream::PrintValueBool(bool b) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%s", b ? "true" : "false");
|
||||
}
|
||||
|
||||
void JSONStream::PrintValue(intptr_t i) {
|
||||
EnsureIntegerIsRepresentableInJavaScript(static_cast<int64_t>(i));
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%" Pd "", i);
|
||||
}
|
||||
|
||||
void JSONStream::PrintValue64(int64_t i) {
|
||||
EnsureIntegerIsRepresentableInJavaScript(i);
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%" Pd64 "", i);
|
||||
}
|
||||
|
||||
void JSONStream::PrintValueTimeMillis(int64_t millis) {
|
||||
EnsureIntegerIsRepresentableInJavaScript(millis);
|
||||
PrintValue64(millis);
|
||||
}
|
||||
|
||||
void JSONStream::PrintValueTimeMicros(int64_t micros) {
|
||||
EnsureIntegerIsRepresentableInJavaScript(micros);
|
||||
PrintValue64(micros);
|
||||
}
|
||||
|
||||
void JSONStream::PrintValue(double d) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%f", d);
|
||||
}
|
||||
|
||||
static const char base64_digits[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char base64_pad = '=';
|
||||
|
||||
void JSONStream::PrintValueBase64(const uint8_t* bytes, intptr_t length) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddChar('"');
|
||||
|
||||
intptr_t odd_bits = length % 3;
|
||||
intptr_t even_bits = length - odd_bits;
|
||||
for (intptr_t i = 0; i < even_bits; i += 3) {
|
||||
intptr_t triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
||||
buffer_.AddChar(base64_digits[triplet >> 18]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 12) & 63]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 6) & 63]);
|
||||
buffer_.AddChar(base64_digits[triplet & 63]);
|
||||
}
|
||||
if (odd_bits == 1) {
|
||||
intptr_t triplet = bytes[even_bits] << 16;
|
||||
buffer_.AddChar(base64_digits[triplet >> 18]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 12) & 63]);
|
||||
buffer_.AddChar(base64_pad);
|
||||
buffer_.AddChar(base64_pad);
|
||||
} else if (odd_bits == 2) {
|
||||
intptr_t triplet = (bytes[even_bits] << 16) | (bytes[even_bits + 1] << 8);
|
||||
buffer_.AddChar(base64_digits[triplet >> 18]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 12) & 63]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 6) & 63]);
|
||||
buffer_.AddChar(base64_pad);
|
||||
}
|
||||
|
||||
buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
void JSONStream::PrintValue(const char* s) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddChar('"');
|
||||
AddEscapedUTF8String(s);
|
||||
buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
bool JSONStream::PrintValueStr(const String& s,
|
||||
intptr_t offset,
|
||||
intptr_t count) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddChar('"');
|
||||
bool did_truncate = AddDartString(s, offset, count);
|
||||
buffer_.AddChar('"');
|
||||
return did_truncate;
|
||||
}
|
||||
|
||||
void JSONStream::PrintValueNoEscape(const char* s) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%s", s);
|
||||
}
|
||||
|
||||
void JSONStream::PrintfValue(const char* format, ...) {
|
||||
PrintCommaIfNeeded();
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
|
||||
VPrintfValue(format, args);
|
||||
va_end(args);
|
||||
MaybeOnStackBuffer mosb(len + 1);
|
||||
char* p = mosb.p();
|
||||
va_start(args, format);
|
||||
intptr_t len2 = OS::VSNPrint(p, len + 1, format, args);
|
||||
va_end(args);
|
||||
ASSERT(len == len2);
|
||||
buffer_.AddChar('"');
|
||||
AddEscapedUTF8String(p, len);
|
||||
buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
void JSONStream::PrintValue(const Object& o, bool ref) {
|
||||
|
@ -562,59 +373,6 @@ void JSONStream::PrintServiceId(const Object& o) {
|
|||
PrintProperty("id", id_zone_->GetServiceId(o));
|
||||
}
|
||||
|
||||
void JSONStream::PrintPropertyBool(const char* name, bool b) {
|
||||
PrintPropertyName(name);
|
||||
PrintValueBool(b);
|
||||
}
|
||||
|
||||
void JSONStream::PrintProperty(const char* name, intptr_t i) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue(i);
|
||||
}
|
||||
|
||||
void JSONStream::PrintProperty64(const char* name, int64_t i) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue64(i);
|
||||
}
|
||||
|
||||
void JSONStream::PrintPropertyTimeMillis(const char* name, int64_t millis) {
|
||||
PrintProperty64(name, millis);
|
||||
}
|
||||
|
||||
void JSONStream::PrintPropertyTimeMicros(const char* name, int64_t micros) {
|
||||
PrintProperty64(name, micros);
|
||||
}
|
||||
|
||||
void JSONStream::PrintProperty(const char* name, double d) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue(d);
|
||||
}
|
||||
|
||||
void JSONStream::PrintProperty(const char* name, const char* s) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue(s);
|
||||
}
|
||||
|
||||
void JSONStream::PrintPropertyBase64(const char* name,
|
||||
const uint8_t* b,
|
||||
intptr_t len) {
|
||||
PrintPropertyName(name);
|
||||
PrintValueBase64(b, len);
|
||||
}
|
||||
|
||||
bool JSONStream::PrintPropertyStr(const char* name,
|
||||
const String& s,
|
||||
intptr_t offset,
|
||||
intptr_t count) {
|
||||
PrintPropertyName(name);
|
||||
return PrintValueStr(s, offset, count);
|
||||
}
|
||||
|
||||
void JSONStream::PrintPropertyNoEscape(const char* name, const char* s) {
|
||||
PrintPropertyName(name);
|
||||
PrintValueNoEscape(s);
|
||||
}
|
||||
|
||||
void JSONStream::PrintProperty(const char* name, const ServiceEvent* event) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue(event);
|
||||
|
@ -668,27 +426,10 @@ void JSONStream::PrintProperty(const char* name,
|
|||
}
|
||||
|
||||
void JSONStream::PrintfProperty(const char* name, const char* format, ...) {
|
||||
PrintPropertyName(name);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
|
||||
writer_.VPrintfProperty(name, format, args);
|
||||
va_end(args);
|
||||
MaybeOnStackBuffer mosb(len + 1);
|
||||
char* p = mosb.p();
|
||||
va_start(args, format);
|
||||
intptr_t len2 = OS::VSNPrint(p, len + 1, format, args);
|
||||
va_end(args);
|
||||
ASSERT(len == len2);
|
||||
buffer_.AddChar('"');
|
||||
AddEscapedUTF8String(p, len);
|
||||
buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
void JSONStream::Steal(char** buffer, intptr_t* buffer_length) {
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(buffer_length != NULL);
|
||||
*buffer_length = buffer_.length();
|
||||
*buffer = buffer_.Steal();
|
||||
}
|
||||
|
||||
void JSONStream::set_reply_port(Dart_Port port) {
|
||||
|
@ -745,106 +486,6 @@ void JSONStream::PrintPropertyVM(const char* name, bool ref) {
|
|||
PrintValueVM(ref);
|
||||
}
|
||||
|
||||
void JSONStream::PrintPropertyName(const char* name) {
|
||||
ASSERT(name != NULL);
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddChar('"');
|
||||
AddEscapedUTF8String(name);
|
||||
buffer_.AddChar('"');
|
||||
buffer_.AddChar(':');
|
||||
}
|
||||
|
||||
void JSONStream::PrintCommaIfNeeded() {
|
||||
if (NeedComma()) {
|
||||
buffer_.AddChar(',');
|
||||
}
|
||||
}
|
||||
|
||||
bool JSONStream::NeedComma() {
|
||||
const char* buffer = buffer_.buf();
|
||||
intptr_t length = buffer_.length();
|
||||
if (length == 0) {
|
||||
return false;
|
||||
}
|
||||
char ch = buffer[length - 1];
|
||||
return (ch != '[') && (ch != '{') && (ch != ':') && (ch != ',');
|
||||
}
|
||||
|
||||
void JSONStream::EnsureIntegerIsRepresentableInJavaScript(int64_t i) {
|
||||
#ifdef DEBUG
|
||||
if (!Utils::IsJavascriptInt(i)) {
|
||||
OS::Print(
|
||||
"JSONStream::EnsureIntegerIsRepresentableInJavaScript failed on "
|
||||
"%" Pd64 "\n",
|
||||
i);
|
||||
UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void JSONStream::AddEscapedUTF8String(const char* s) {
|
||||
if (s == NULL) {
|
||||
return;
|
||||
}
|
||||
intptr_t len = strlen(s);
|
||||
AddEscapedUTF8String(s, len);
|
||||
}
|
||||
|
||||
void JSONStream::AddEscapedUTF8String(const char* s, intptr_t len) {
|
||||
if (s == NULL) {
|
||||
return;
|
||||
}
|
||||
const uint8_t* s8 = reinterpret_cast<const uint8_t*>(s);
|
||||
intptr_t i = 0;
|
||||
for (; i < len;) {
|
||||
// Extract next UTF8 character.
|
||||
int32_t ch = 0;
|
||||
int32_t ch_len = Utf8::Decode(&s8[i], len - i, &ch);
|
||||
ASSERT(ch_len != 0);
|
||||
buffer_.EscapeAndAddCodeUnit(ch);
|
||||
// Move i forward.
|
||||
i += ch_len;
|
||||
}
|
||||
ASSERT(i == len);
|
||||
}
|
||||
|
||||
bool JSONStream::AddDartString(const String& s,
|
||||
intptr_t offset,
|
||||
intptr_t count) {
|
||||
intptr_t length = s.Length();
|
||||
ASSERT(offset >= 0);
|
||||
if (offset > length) {
|
||||
offset = length;
|
||||
}
|
||||
if (!Utils::RangeCheck(offset, count, length)) {
|
||||
count = length - offset;
|
||||
}
|
||||
intptr_t limit = offset + count;
|
||||
for (intptr_t i = offset; i < limit; i++) {
|
||||
uint16_t code_unit = s.CharAt(i);
|
||||
if (Utf16::IsTrailSurrogate(code_unit)) {
|
||||
buffer_.EscapeAndAddUTF16CodeUnit(code_unit);
|
||||
} else if (Utf16::IsLeadSurrogate(code_unit)) {
|
||||
if (i + 1 == limit) {
|
||||
buffer_.EscapeAndAddUTF16CodeUnit(code_unit);
|
||||
} else {
|
||||
uint16_t next_code_unit = s.CharAt(i + 1);
|
||||
if (Utf16::IsTrailSurrogate(next_code_unit)) {
|
||||
uint32_t decoded = Utf16::Decode(code_unit, next_code_unit);
|
||||
buffer_.EscapeAndAddCodeUnit(decoded);
|
||||
i++;
|
||||
} else {
|
||||
buffer_.EscapeAndAddUTF16CodeUnit(code_unit);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buffer_.EscapeAndAddCodeUnit(code_unit);
|
||||
}
|
||||
}
|
||||
// Return value indicates whether the string is truncated.
|
||||
return (offset > 0) || (limit < length);
|
||||
}
|
||||
|
||||
JSONObject::JSONObject(const JSONArray* arr) : stream_(arr->stream_) {
|
||||
stream_->OpenObject();
|
||||
}
|
||||
|
@ -853,20 +494,10 @@ void JSONObject::AddFixedServiceId(const char* format, ...) const {
|
|||
// Mark that this id is fixed.
|
||||
AddProperty("fixedId", true);
|
||||
// Add the id property.
|
||||
stream_->PrintPropertyName("id");
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
|
||||
stream_->VPrintfProperty("id", format, args);
|
||||
va_end(args);
|
||||
MaybeOnStackBuffer mosb(len + 1);
|
||||
char* p = mosb.p();
|
||||
va_start(args, format);
|
||||
intptr_t len2 = OS::VSNPrint(p, len + 1, format, args);
|
||||
va_end(args);
|
||||
ASSERT(len == len2);
|
||||
stream_->buffer_.AddChar('"');
|
||||
stream_->AddEscapedUTF8String(p, len);
|
||||
stream_->buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
void JSONObject::AddLocation(const Script& script,
|
||||
|
@ -923,37 +554,17 @@ void JSONObject::AddUnresolvedLocation(
|
|||
}
|
||||
|
||||
void JSONObject::AddPropertyF(const char* name, const char* format, ...) const {
|
||||
stream_->PrintPropertyName(name);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
|
||||
stream_->VPrintfProperty(name, format, args);
|
||||
va_end(args);
|
||||
MaybeOnStackBuffer mosb(len + 1);
|
||||
char* p = mosb.p();
|
||||
va_start(args, format);
|
||||
intptr_t len2 = OS::VSNPrint(p, len + 1, format, args);
|
||||
va_end(args);
|
||||
ASSERT(len == len2);
|
||||
stream_->buffer_.AddChar('"');
|
||||
stream_->AddEscapedUTF8String(p, len);
|
||||
stream_->buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
void JSONArray::AddValueF(const char* format, ...) const {
|
||||
stream_->PrintCommaIfNeeded();
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
|
||||
stream_->VPrintfValue(format, args);
|
||||
va_end(args);
|
||||
MaybeOnStackBuffer mosb(len + 1);
|
||||
char* p = mosb.p();
|
||||
va_start(args, format);
|
||||
intptr_t len2 = OS::VSNPrint(p, len + 1, format, args);
|
||||
va_end(args);
|
||||
ASSERT(len == len2);
|
||||
stream_->buffer_.AddChar('"');
|
||||
stream_->AddEscapedUTF8String(p, len);
|
||||
stream_->buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
#endif // !PRODUCT
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
#define RUNTIME_VM_JSON_STREAM_H_
|
||||
|
||||
#include "include/dart_api.h" // for Dart_Port
|
||||
#include "platform/allocation.h"
|
||||
#include "platform/text_buffer.h"
|
||||
#include "vm/allocation.h"
|
||||
#include "vm/json_writer.h"
|
||||
#include "vm/service.h"
|
||||
#include "vm/token_position.h"
|
||||
|
||||
|
@ -64,10 +65,11 @@ enum JSONRpcErrorCode {
|
|||
kFileDoesNotExist = 1003,
|
||||
};
|
||||
|
||||
// Builds on JSONWriter to provide support for serializing various objects
|
||||
// used in the VM service protocol.
|
||||
class JSONStream : ValueObject {
|
||||
public:
|
||||
explicit JSONStream(intptr_t buf_size = 256);
|
||||
~JSONStream();
|
||||
|
||||
void Setup(Zone* zone,
|
||||
Dart_Port reply_port,
|
||||
|
@ -85,10 +87,12 @@ class JSONStream : ValueObject {
|
|||
void set_id_zone(ServiceIdZone* id_zone) { id_zone_ = id_zone; }
|
||||
ServiceIdZone* id_zone() { return id_zone_; }
|
||||
|
||||
TextBuffer* buffer() { return &buffer_; }
|
||||
const char* ToCString() { return buffer_.buf(); }
|
||||
TextBuffer* buffer() { return writer_.buffer(); }
|
||||
const char* ToCString() { return writer_.ToCString(); }
|
||||
|
||||
void Steal(char** buffer, intptr_t* buffer_length);
|
||||
void Steal(char** buffer, intptr_t* buffer_length) {
|
||||
writer_.Steal(buffer, buffer_length);
|
||||
}
|
||||
|
||||
void set_reply_port(Dart_Port port);
|
||||
|
||||
|
@ -134,40 +138,59 @@ class JSONStream : ValueObject {
|
|||
intptr_t* count);
|
||||
|
||||
// Append |serialized_object| to the stream.
|
||||
void AppendSerializedObject(const char* serialized_object);
|
||||
|
||||
void PrintCommaIfNeeded();
|
||||
void AppendSerializedObject(const char* serialized_object) {
|
||||
writer_.AppendSerializedObject(serialized_object);
|
||||
}
|
||||
|
||||
// Append |buffer| to the stream.
|
||||
void AppendSerializedObject(const uint8_t* buffer, intptr_t buffer_length);
|
||||
void AppendSerializedObject(const uint8_t* buffer, intptr_t buffer_length) {
|
||||
writer_.AppendSerializedObject(buffer, buffer_length);
|
||||
}
|
||||
|
||||
// Append |serialized_object| to the stream with |property_name|.
|
||||
void AppendSerializedObject(const char* property_name,
|
||||
const char* serialized_object);
|
||||
const char* serialized_object) {
|
||||
writer_.AppendSerializedObject(property_name, serialized_object);
|
||||
}
|
||||
|
||||
void PrintCommaIfNeeded() { writer_.PrintCommaIfNeeded(); }
|
||||
|
||||
private:
|
||||
void Clear();
|
||||
void Clear() { writer_.Clear(); }
|
||||
|
||||
void PostNullReply(Dart_Port port);
|
||||
|
||||
void OpenObject(const char* property_name = NULL);
|
||||
void CloseObject();
|
||||
void UncloseObject();
|
||||
void OpenObject(const char* property_name = NULL) {
|
||||
writer_.OpenObject(property_name);
|
||||
}
|
||||
void CloseObject() { writer_.CloseObject(); }
|
||||
void UncloseObject() { writer_.UncloseObject(); }
|
||||
|
||||
void OpenArray(const char* property_name = NULL);
|
||||
void CloseArray();
|
||||
void OpenArray(const char* property_name = NULL) {
|
||||
writer_.OpenArray(property_name);
|
||||
}
|
||||
void CloseArray() { writer_.CloseArray(); }
|
||||
|
||||
void PrintValueNull();
|
||||
void PrintValueBool(bool b);
|
||||
void PrintValue(intptr_t i);
|
||||
void PrintValue64(int64_t i);
|
||||
void PrintValueTimeMillis(int64_t millis);
|
||||
void PrintValueTimeMicros(int64_t micros);
|
||||
void PrintValue(double d);
|
||||
void PrintValueBase64(const uint8_t* bytes, intptr_t length);
|
||||
void PrintValue(const char* s);
|
||||
void PrintValue(const char* s, intptr_t len);
|
||||
void PrintValueNoEscape(const char* s);
|
||||
void PrintValueNull() { writer_.PrintValueNull(); }
|
||||
void PrintValueBool(bool b) { writer_.PrintValueBool(b); }
|
||||
void PrintValue(intptr_t i) { writer_.PrintValue(i); }
|
||||
void PrintValue64(int64_t i) { writer_.PrintValue64(i); }
|
||||
void PrintValueTimeMillis(int64_t millis) { writer_.PrintValue64(millis); }
|
||||
void PrintValueTimeMicros(int64_t micros) { writer_.PrintValue64(micros); }
|
||||
void PrintValue(double d) { writer_.PrintValue(d); }
|
||||
void PrintValueBase64(const uint8_t* bytes, intptr_t length) {
|
||||
writer_.PrintValueBase64(bytes, length);
|
||||
}
|
||||
void PrintValue(const char* s) { writer_.PrintValue(s); }
|
||||
void PrintValueNoEscape(const char* s) { writer_.PrintValueNoEscape(s); }
|
||||
bool PrintValueStr(const String& s, intptr_t offset, intptr_t count) {
|
||||
return writer_.PrintValueStr(s, offset, count);
|
||||
}
|
||||
void PrintfValue(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
void VPrintfValue(const char* format, va_list args) {
|
||||
writer_.VPrintfValue(format, args);
|
||||
}
|
||||
|
||||
void PrintValue(const Object& o, bool ref = true);
|
||||
void PrintValue(Breakpoint* bpt);
|
||||
void PrintValue(TokenPosition tp);
|
||||
|
@ -177,29 +200,52 @@ class JSONStream : ValueObject {
|
|||
void PrintValue(Isolate* isolate, bool ref = true);
|
||||
void PrintValue(ThreadRegistry* reg);
|
||||
void PrintValue(Thread* thread);
|
||||
bool PrintValueStr(const String& s, intptr_t offset, intptr_t count);
|
||||
void PrintValue(const TimelineEvent* timeline_event);
|
||||
void PrintValue(const TimelineEventBlock* timeline_event_block);
|
||||
void PrintValueVM(bool ref = true);
|
||||
|
||||
void PrintServiceId(const Object& o);
|
||||
void PrintPropertyBool(const char* name, bool b);
|
||||
void PrintProperty(const char* name, intptr_t i);
|
||||
void PrintProperty64(const char* name, int64_t i);
|
||||
void PrintPropertyTimeMillis(const char* name, int64_t millis);
|
||||
void PrintPropertyTimeMicros(const char* name, int64_t micros);
|
||||
void PrintProperty(const char* name, double d);
|
||||
|
||||
void PrintPropertyBool(const char* name, bool b) {
|
||||
writer_.PrintPropertyBool(name, b);
|
||||
}
|
||||
void PrintProperty(const char* name, intptr_t i) {
|
||||
writer_.PrintProperty(name, i);
|
||||
}
|
||||
void PrintProperty64(const char* name, int64_t i) {
|
||||
writer_.PrintProperty64(name, i);
|
||||
}
|
||||
void PrintPropertyTimeMillis(const char* name, int64_t millis) {
|
||||
writer_.PrintProperty64(name, millis);
|
||||
}
|
||||
void PrintPropertyTimeMicros(const char* name, int64_t micros) {
|
||||
writer_.PrintProperty64(name, micros);
|
||||
}
|
||||
void PrintProperty(const char* name, double d) {
|
||||
writer_.PrintProperty(name, d);
|
||||
}
|
||||
void PrintPropertyBase64(const char* name,
|
||||
const uint8_t* bytes,
|
||||
intptr_t length);
|
||||
void PrintProperty(const char* name, const char* s);
|
||||
intptr_t length) {
|
||||
writer_.PrintPropertyBase64(name, bytes, length);
|
||||
}
|
||||
void PrintProperty(const char* name, const char* s) {
|
||||
writer_.PrintProperty(name, s);
|
||||
}
|
||||
bool PrintPropertyStr(const char* name,
|
||||
const String& s,
|
||||
intptr_t offset,
|
||||
intptr_t count);
|
||||
void PrintPropertyNoEscape(const char* name, const char* s);
|
||||
intptr_t count) {
|
||||
return writer_.PrintPropertyStr(name, s, offset, count);
|
||||
}
|
||||
void PrintPropertyNoEscape(const char* name, const char* s) {
|
||||
writer_.PrintPropertyNoEscape(name, s);
|
||||
}
|
||||
void PrintfProperty(const char* name, const char* format, ...)
|
||||
PRINTF_ATTRIBUTE(3, 4);
|
||||
void VPrintfProperty(const char* name, const char* format, va_list args) {
|
||||
writer_.VPrintfProperty(name, format, args);
|
||||
}
|
||||
void PrintProperty(const char* name, const Object& o, bool ref = true);
|
||||
|
||||
void PrintProperty(const char* name, const ServiceEvent* event);
|
||||
|
@ -215,20 +261,13 @@ class JSONStream : ValueObject {
|
|||
void PrintProperty(const char* name,
|
||||
const TimelineEventBlock* timeline_event_block);
|
||||
void PrintPropertyVM(const char* name, bool ref = true);
|
||||
void PrintPropertyName(const char* name);
|
||||
bool NeedComma();
|
||||
void PrintPropertyName(const char* name) { writer_.PrintPropertyName(name); }
|
||||
|
||||
bool AddDartString(const String& s, intptr_t offset, intptr_t count);
|
||||
void AddEscapedUTF8String(const char* s);
|
||||
void AddEscapedUTF8String(const char* s, intptr_t len);
|
||||
void AddEscapedUTF8String(const char* s, intptr_t len) {
|
||||
writer_.AddEscapedUTF8String(s, len);
|
||||
}
|
||||
|
||||
intptr_t nesting_level() const { return open_objects_; }
|
||||
|
||||
// Debug only fatal assertion.
|
||||
static void EnsureIntegerIsRepresentableInJavaScript(int64_t i);
|
||||
|
||||
intptr_t open_objects_;
|
||||
TextBuffer buffer_;
|
||||
JSONWriter writer_;
|
||||
// Default service id zone.
|
||||
RingServiceIdZone default_id_zone_;
|
||||
ServiceIdZone* id_zone_;
|
||||
|
|
392
runtime/vm/json_writer.cc
Normal file
392
runtime/vm/json_writer.cc
Normal file
|
@ -0,0 +1,392 @@
|
|||
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "platform/assert.h"
|
||||
|
||||
#include "vm/json_writer.h"
|
||||
#include "vm/object.h"
|
||||
#include "vm/unicode.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
class MaybeOnStackBuffer {
|
||||
public:
|
||||
explicit MaybeOnStackBuffer(intptr_t size) {
|
||||
if (size > kOnStackBufferCapacity) {
|
||||
p_ = reinterpret_cast<char*>(malloc(size));
|
||||
} else {
|
||||
p_ = &buffer_[0];
|
||||
}
|
||||
}
|
||||
~MaybeOnStackBuffer() {
|
||||
if (p_ != &buffer_[0]) free(p_);
|
||||
}
|
||||
|
||||
char* p() { return p_; }
|
||||
|
||||
private:
|
||||
static const intptr_t kOnStackBufferCapacity = 4096;
|
||||
char* p_;
|
||||
char buffer_[kOnStackBufferCapacity];
|
||||
};
|
||||
|
||||
JSONWriter::JSONWriter(intptr_t buf_size)
|
||||
: open_objects_(0), buffer_(buf_size) {}
|
||||
|
||||
void JSONWriter::AppendSerializedObject(const char* serialized_object) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddString(serialized_object);
|
||||
}
|
||||
|
||||
void JSONWriter::AppendSerializedObject(const uint8_t* buffer,
|
||||
intptr_t buffer_length) {
|
||||
buffer_.AddRaw(buffer, buffer_length);
|
||||
}
|
||||
|
||||
void JSONWriter::AppendSerializedObject(const char* property_name,
|
||||
const char* serialized_object) {
|
||||
PrintCommaIfNeeded();
|
||||
PrintPropertyName(property_name);
|
||||
buffer_.AddString(serialized_object);
|
||||
}
|
||||
|
||||
void JSONWriter::Clear() {
|
||||
buffer_.Clear();
|
||||
open_objects_ = 0;
|
||||
}
|
||||
|
||||
void JSONWriter::OpenObject(const char* property_name) {
|
||||
PrintCommaIfNeeded();
|
||||
open_objects_++;
|
||||
if (property_name != NULL) {
|
||||
PrintPropertyName(property_name);
|
||||
}
|
||||
buffer_.AddChar('{');
|
||||
}
|
||||
|
||||
void JSONWriter::UncloseObject() {
|
||||
intptr_t len = buffer_.length();
|
||||
ASSERT(len > 0);
|
||||
ASSERT(buffer_.buf()[len - 1] == '}');
|
||||
open_objects_++;
|
||||
buffer_.set_length(len - 1);
|
||||
}
|
||||
|
||||
void JSONWriter::CloseObject() {
|
||||
ASSERT(open_objects_ > 0);
|
||||
open_objects_--;
|
||||
buffer_.AddChar('}');
|
||||
}
|
||||
|
||||
void JSONWriter::OpenArray(const char* property_name) {
|
||||
PrintCommaIfNeeded();
|
||||
if (property_name != NULL) {
|
||||
PrintPropertyName(property_name);
|
||||
}
|
||||
open_objects_++;
|
||||
buffer_.AddChar('[');
|
||||
}
|
||||
|
||||
void JSONWriter::CloseArray() {
|
||||
ASSERT(open_objects_ > 0);
|
||||
open_objects_--;
|
||||
buffer_.AddChar(']');
|
||||
}
|
||||
|
||||
void JSONWriter::PrintValueNull() {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("null");
|
||||
}
|
||||
|
||||
void JSONWriter::PrintValueBool(bool b) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%s", b ? "true" : "false");
|
||||
}
|
||||
|
||||
void JSONWriter::PrintValue(intptr_t i) {
|
||||
EnsureIntegerIsRepresentableInJavaScript(static_cast<int64_t>(i));
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%" Pd "", i);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintValue64(int64_t i) {
|
||||
EnsureIntegerIsRepresentableInJavaScript(i);
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%" Pd64 "", i);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintValue(double d) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%f", d);
|
||||
}
|
||||
|
||||
static const char base64_digits[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char base64_pad = '=';
|
||||
|
||||
void JSONWriter::PrintValueBase64(const uint8_t* bytes, intptr_t length) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddChar('"');
|
||||
|
||||
intptr_t odd_bits = length % 3;
|
||||
intptr_t even_bits = length - odd_bits;
|
||||
for (intptr_t i = 0; i < even_bits; i += 3) {
|
||||
intptr_t triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
||||
buffer_.AddChar(base64_digits[triplet >> 18]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 12) & 63]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 6) & 63]);
|
||||
buffer_.AddChar(base64_digits[triplet & 63]);
|
||||
}
|
||||
if (odd_bits == 1) {
|
||||
intptr_t triplet = bytes[even_bits] << 16;
|
||||
buffer_.AddChar(base64_digits[triplet >> 18]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 12) & 63]);
|
||||
buffer_.AddChar(base64_pad);
|
||||
buffer_.AddChar(base64_pad);
|
||||
} else if (odd_bits == 2) {
|
||||
intptr_t triplet = (bytes[even_bits] << 16) | (bytes[even_bits + 1] << 8);
|
||||
buffer_.AddChar(base64_digits[triplet >> 18]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 12) & 63]);
|
||||
buffer_.AddChar(base64_digits[(triplet >> 6) & 63]);
|
||||
buffer_.AddChar(base64_pad);
|
||||
}
|
||||
|
||||
buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
void JSONWriter::PrintValue(const char* s) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddChar('"');
|
||||
AddEscapedUTF8String(s);
|
||||
buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
bool JSONWriter::PrintValueStr(const String& s,
|
||||
intptr_t offset,
|
||||
intptr_t count) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddChar('"');
|
||||
bool did_truncate = AddDartString(s, offset, count);
|
||||
buffer_.AddChar('"');
|
||||
return did_truncate;
|
||||
}
|
||||
|
||||
void JSONWriter::PrintValueNoEscape(const char* s) {
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.Printf("%s", s);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintfValue(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VPrintfValue(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void JSONWriter::VPrintfValue(const char* format, va_list args) {
|
||||
PrintCommaIfNeeded();
|
||||
|
||||
va_list measure_args;
|
||||
va_copy(measure_args, args);
|
||||
intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
|
||||
va_end(measure_args);
|
||||
|
||||
MaybeOnStackBuffer mosb(len + 1);
|
||||
char* p = mosb.p();
|
||||
|
||||
va_list print_args;
|
||||
va_copy(print_args, args);
|
||||
intptr_t len2 = OS::VSNPrint(p, len + 1, format, print_args);
|
||||
va_end(print_args);
|
||||
ASSERT(len == len2);
|
||||
|
||||
buffer_.AddChar('"');
|
||||
AddEscapedUTF8String(p, len);
|
||||
buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
void JSONWriter::PrintPropertyBool(const char* name, bool b) {
|
||||
PrintPropertyName(name);
|
||||
PrintValueBool(b);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintProperty(const char* name, intptr_t i) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue(i);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintProperty64(const char* name, int64_t i) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue64(i);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintProperty(const char* name, double d) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue(d);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintProperty(const char* name, const char* s) {
|
||||
PrintPropertyName(name);
|
||||
PrintValue(s);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintPropertyBase64(const char* name,
|
||||
const uint8_t* b,
|
||||
intptr_t len) {
|
||||
PrintPropertyName(name);
|
||||
PrintValueBase64(b, len);
|
||||
}
|
||||
|
||||
bool JSONWriter::PrintPropertyStr(const char* name,
|
||||
const String& s,
|
||||
intptr_t offset,
|
||||
intptr_t count) {
|
||||
PrintPropertyName(name);
|
||||
return PrintValueStr(s, offset, count);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintPropertyNoEscape(const char* name, const char* s) {
|
||||
PrintPropertyName(name);
|
||||
PrintValueNoEscape(s);
|
||||
}
|
||||
|
||||
void JSONWriter::PrintfProperty(const char* name, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VPrintfProperty(name, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void JSONWriter::VPrintfProperty(const char* name,
|
||||
const char* format,
|
||||
va_list args) {
|
||||
PrintPropertyName(name);
|
||||
|
||||
va_list measure_args;
|
||||
va_copy(measure_args, args);
|
||||
intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
|
||||
va_end(measure_args);
|
||||
|
||||
MaybeOnStackBuffer mosb(len + 1);
|
||||
char* p = mosb.p();
|
||||
|
||||
va_list print_args;
|
||||
va_copy(print_args, args);
|
||||
intptr_t len2 = OS::VSNPrint(p, len + 1, format, print_args);
|
||||
va_end(print_args);
|
||||
ASSERT(len == len2);
|
||||
|
||||
buffer_.AddChar('"');
|
||||
AddEscapedUTF8String(p, len);
|
||||
buffer_.AddChar('"');
|
||||
}
|
||||
|
||||
void JSONWriter::Steal(char** buffer, intptr_t* buffer_length) {
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(buffer_length != NULL);
|
||||
*buffer_length = buffer_.length();
|
||||
*buffer = buffer_.Steal();
|
||||
}
|
||||
|
||||
void JSONWriter::PrintPropertyName(const char* name) {
|
||||
ASSERT(name != NULL);
|
||||
PrintCommaIfNeeded();
|
||||
buffer_.AddChar('"');
|
||||
AddEscapedUTF8String(name);
|
||||
buffer_.AddChar('"');
|
||||
buffer_.AddChar(':');
|
||||
}
|
||||
|
||||
void JSONWriter::PrintCommaIfNeeded() {
|
||||
if (NeedComma()) {
|
||||
buffer_.AddChar(',');
|
||||
}
|
||||
}
|
||||
|
||||
bool JSONWriter::NeedComma() {
|
||||
const char* buffer = buffer_.buf();
|
||||
intptr_t length = buffer_.length();
|
||||
if (length == 0) {
|
||||
return false;
|
||||
}
|
||||
char ch = buffer[length - 1];
|
||||
return (ch != '[') && (ch != '{') && (ch != ':') && (ch != ',');
|
||||
}
|
||||
|
||||
void JSONWriter::EnsureIntegerIsRepresentableInJavaScript(int64_t i) {
|
||||
#ifdef DEBUG
|
||||
if (!Utils::IsJavascriptInt(i)) {
|
||||
OS::Print(
|
||||
"JSONWriter::EnsureIntegerIsRepresentableInJavaScript failed on "
|
||||
"%" Pd64 "\n",
|
||||
i);
|
||||
UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void JSONWriter::AddEscapedUTF8String(const char* s) {
|
||||
if (s == NULL) {
|
||||
return;
|
||||
}
|
||||
intptr_t len = strlen(s);
|
||||
AddEscapedUTF8String(s, len);
|
||||
}
|
||||
|
||||
void JSONWriter::AddEscapedUTF8String(const char* s, intptr_t len) {
|
||||
if (s == NULL) {
|
||||
return;
|
||||
}
|
||||
const uint8_t* s8 = reinterpret_cast<const uint8_t*>(s);
|
||||
intptr_t i = 0;
|
||||
for (; i < len;) {
|
||||
// Extract next UTF8 character.
|
||||
int32_t ch = 0;
|
||||
int32_t ch_len = Utf8::Decode(&s8[i], len - i, &ch);
|
||||
ASSERT(ch_len != 0);
|
||||
buffer_.EscapeAndAddCodeUnit(ch);
|
||||
// Move i forward.
|
||||
i += ch_len;
|
||||
}
|
||||
ASSERT(i == len);
|
||||
}
|
||||
|
||||
bool JSONWriter::AddDartString(const String& s,
|
||||
intptr_t offset,
|
||||
intptr_t count) {
|
||||
intptr_t length = s.Length();
|
||||
ASSERT(offset >= 0);
|
||||
if (offset > length) {
|
||||
offset = length;
|
||||
}
|
||||
if (!Utils::RangeCheck(offset, count, length)) {
|
||||
count = length - offset;
|
||||
}
|
||||
intptr_t limit = offset + count;
|
||||
for (intptr_t i = offset; i < limit; i++) {
|
||||
uint16_t code_unit = s.CharAt(i);
|
||||
if (Utf16::IsTrailSurrogate(code_unit)) {
|
||||
buffer_.EscapeAndAddUTF16CodeUnit(code_unit);
|
||||
} else if (Utf16::IsLeadSurrogate(code_unit)) {
|
||||
if (i + 1 == limit) {
|
||||
buffer_.EscapeAndAddUTF16CodeUnit(code_unit);
|
||||
} else {
|
||||
uint16_t next_code_unit = s.CharAt(i + 1);
|
||||
if (Utf16::IsTrailSurrogate(next_code_unit)) {
|
||||
uint32_t decoded = Utf16::Decode(code_unit, next_code_unit);
|
||||
buffer_.EscapeAndAddCodeUnit(decoded);
|
||||
i++;
|
||||
} else {
|
||||
buffer_.EscapeAndAddUTF16CodeUnit(code_unit);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buffer_.EscapeAndAddCodeUnit(code_unit);
|
||||
}
|
||||
}
|
||||
// Return value indicates whether the string is truncated.
|
||||
return (offset > 0) || (limit < length);
|
||||
}
|
||||
|
||||
} // namespace dart
|
93
runtime/vm/json_writer.h
Normal file
93
runtime/vm/json_writer.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef RUNTIME_VM_JSON_WRITER_H_
|
||||
#define RUNTIME_VM_JSON_WRITER_H_
|
||||
|
||||
#include "platform/allocation.h"
|
||||
#include "platform/text_buffer.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
class String;
|
||||
|
||||
class JSONWriter : ValueObject {
|
||||
public:
|
||||
explicit JSONWriter(intptr_t buf_size = 256);
|
||||
|
||||
TextBuffer* buffer() { return &buffer_; }
|
||||
const char* ToCString() { return buffer_.buf(); }
|
||||
|
||||
void Steal(char** buffer, intptr_t* buffer_length);
|
||||
|
||||
void PrintCommaIfNeeded();
|
||||
|
||||
// Append |serialized_object| to the stream.
|
||||
void AppendSerializedObject(const char* serialized_object);
|
||||
|
||||
// Append |buffer| to the stream.
|
||||
void AppendSerializedObject(const uint8_t* buffer, intptr_t buffer_length);
|
||||
|
||||
// Append |serialized_object| to the stream with |property_name|.
|
||||
void AppendSerializedObject(const char* property_name,
|
||||
const char* serialized_object);
|
||||
|
||||
void OpenObject(const char* property_name = NULL);
|
||||
void CloseObject();
|
||||
void UncloseObject();
|
||||
|
||||
void OpenArray(const char* property_name = NULL);
|
||||
void CloseArray();
|
||||
|
||||
void Clear();
|
||||
|
||||
void PrintValueNull();
|
||||
void PrintValueBool(bool b);
|
||||
void PrintValue(intptr_t i);
|
||||
void PrintValue64(int64_t i);
|
||||
void PrintValue(double d);
|
||||
void PrintValueBase64(const uint8_t* bytes, intptr_t length);
|
||||
void PrintValue(const char* s);
|
||||
void PrintValue(const char* s, intptr_t len);
|
||||
void PrintValueNoEscape(const char* s);
|
||||
void PrintfValue(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
void VPrintfValue(const char* format, va_list args);
|
||||
bool PrintValueStr(const String& s, intptr_t offset, intptr_t count);
|
||||
|
||||
void PrintPropertyBool(const char* name, bool b);
|
||||
void PrintProperty(const char* name, intptr_t i);
|
||||
void PrintProperty64(const char* name, int64_t i);
|
||||
void PrintProperty(const char* name, double d);
|
||||
void PrintPropertyBase64(const char* name,
|
||||
const uint8_t* bytes,
|
||||
intptr_t length);
|
||||
void PrintProperty(const char* name, const char* s);
|
||||
bool PrintPropertyStr(const char* name,
|
||||
const String& s,
|
||||
intptr_t offset = 0,
|
||||
intptr_t count = -1);
|
||||
void PrintPropertyNoEscape(const char* name, const char* s);
|
||||
void PrintfProperty(const char* name, const char* format, ...)
|
||||
PRINTF_ATTRIBUTE(3, 4);
|
||||
void VPrintfProperty(const char* name, const char* format, va_list args);
|
||||
|
||||
void PrintPropertyName(const char* name);
|
||||
|
||||
void AddEscapedUTF8String(const char* s);
|
||||
void AddEscapedUTF8String(const char* s, intptr_t len);
|
||||
|
||||
private:
|
||||
bool NeedComma();
|
||||
bool AddDartString(const String& s, intptr_t offset, intptr_t count);
|
||||
|
||||
// Debug only fatal assertion.
|
||||
static void EnsureIntegerIsRepresentableInJavaScript(int64_t i);
|
||||
|
||||
intptr_t open_objects_;
|
||||
TextBuffer buffer_;
|
||||
};
|
||||
|
||||
} // namespace dart
|
||||
|
||||
#endif // RUNTIME_VM_JSON_WRITER_H_
|
|
@ -140,6 +140,8 @@ vm_sources = [
|
|||
"json_parser.h",
|
||||
"json_stream.cc",
|
||||
"json_stream.h",
|
||||
"json_writer.cc",
|
||||
"json_writer.h",
|
||||
"kernel.cc",
|
||||
"kernel.h",
|
||||
"kernel_binary.cc",
|
||||
|
|
Loading…
Reference in a new issue