// Copyright (c) 2013, 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_STREAM_H_ #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/json_writer.h" #include "vm/service.h" #include "vm/token_position.h" namespace dart { class Array; class Breakpoint; class BreakpointLocation; class Field; class GrowableObjectArray; class Instance; class JSONArray; class JSONObject; class MessageQueue; class Metric; class Object; class Script; class ServiceEvent; class String; class TimelineEvent; class TimelineEventBlock; class Thread; class ThreadRegistry; class Zone; // Keep this enum in sync with: // // - runtime/vm/service/vmservice.dart // - runtime/observatory/lib/src/service/object.dart // - pkg/dds/lib/src/rpc_error_codes.dart // enum JSONRpcErrorCode { kParseError = -32700, kInvalidRequest = -32600, kMethodNotFound = -32601, kInvalidParams = -32602, kInternalError = -32603, kExtensionError = -32000, kFeatureDisabled = 100, kCannotAddBreakpoint = 102, kStreamAlreadySubscribed = 103, kStreamNotSubscribed = 104, kIsolateMustBeRunnable = 105, kIsolateMustBePaused = 106, kCannotResume = 107, kIsolateIsReloading = 108, kIsolateReloadBarred = 109, kIsolateMustHaveReloaded = 110, kServiceAlreadyRegistered = 111, kServiceDisappeared = 112, kExpressionCompilationError = 113, kInvalidTimelineRequest = 114, // Experimental (used in private rpcs). kFileSystemAlreadyExists = 1001, kFileSystemDoesNotExist = 1002, 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); void Setup(Zone* zone, Dart_Port reply_port, const Instance& seq, const String& method, const Array& param_keys, const Array& param_values, bool parameters_are_dart_objects = false); void SetupError(); void PrintError(intptr_t code, const char* details_format, ...) PRINTF_ATTRIBUTE(3, 4); void PostReply(); void set_id_zone(ServiceIdZone* id_zone) { id_zone_ = id_zone; } ServiceIdZone* id_zone() { return id_zone_; } TextBuffer* buffer() { return writer_.buffer(); } const char* ToCString() { return writer_.ToCString(); } void Steal(char** buffer, intptr_t* buffer_length) { writer_.Steal(buffer, buffer_length); } void set_reply_port(Dart_Port port); void SetParams(const char** param_keys, const char** param_values, intptr_t num_params); Dart_Port reply_port() const { return reply_port_; } intptr_t NumObjectParameters() const; ObjectPtr GetObjectParameterKey(intptr_t i) const; ObjectPtr GetObjectParameterValue(intptr_t i) const; ObjectPtr LookupObjectParam(const char* key) const; intptr_t num_params() const { return num_params_; } const char* GetParamKey(intptr_t i) const { return param_keys_[i]; } const char* GetParamValue(intptr_t i) const { return param_values_[i]; } const char* LookupParam(const char* key) const; bool HasParam(const char* key) const; // Returns true if there is an param with key and value, false // otherwise. bool ParamIs(const char* key, const char* value) const; const char* method() const { return method_; } const char** param_keys() const { return param_keys_; } const char** param_values() const { return param_values_; } void set_offset(intptr_t value) { ASSERT(value > 0); offset_ = value; } void set_count(intptr_t value) { ASSERT(value > 0); count_ = value; } void ComputeOffsetAndCount(intptr_t length, intptr_t* offset, intptr_t* count); // Append |serialized_object| to the stream. 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) { writer_.AppendSerializedObject(buffer, buffer_length); } // Append |serialized_object| to the stream with |property_name|. void AppendSerializedObject(const char* property_name, const char* serialized_object) { writer_.AppendSerializedObject(property_name, serialized_object); } void PrintCommaIfNeeded() { writer_.PrintCommaIfNeeded(); } private: void Clear() { writer_.Clear(); } void PostNullReply(Dart_Port port); 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) { writer_.OpenArray(property_name); } void CloseArray() { writer_.CloseArray(); } 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); void PrintValue(const ServiceEvent* event); void PrintValue(Metric* metric); void PrintValue(MessageQueue* queue); void PrintValue(Isolate* isolate, bool ref = true); void PrintValue(IsolateGroup* isolate, bool ref = true); 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) { 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) { 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) { 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); void PrintProperty(const char* name, Breakpoint* bpt); void PrintProperty(const char* name, TokenPosition tp); void PrintProperty(const char* name, Metric* metric); void PrintProperty(const char* name, MessageQueue* queue); void PrintProperty(const char* name, Isolate* isolate); void PrintProperty(const char* name, Zone* zone); void PrintProperty(const char* name, const TimelineEvent* timeline_event); void PrintProperty(const char* name, const TimelineEventBlock* timeline_event_block); void PrintPropertyVM(const char* name, bool ref = true); void PrintPropertyName(const char* name) { writer_.PrintPropertyName(name); } void AddEscapedUTF8String(const char* s, intptr_t len) { writer_.AddEscapedUTF8String(s, len); } JSONWriter writer_; // Default service id zone. RingServiceIdZone default_id_zone_; ServiceIdZone* id_zone_; Dart_Port reply_port_; Instance* seq_; Array* parameter_keys_; Array* parameter_values_; const char* method_; const char** param_keys_; const char** param_values_; intptr_t num_params_; intptr_t offset_; intptr_t count_; int64_t setup_time_micros_; friend class JSONObject; friend class JSONArray; friend class TimelineEvent; }; class JSONObject : public ValueObject { public: explicit JSONObject(JSONStream* stream) : stream_(stream) { stream_->OpenObject(); } JSONObject(const JSONObject* obj, const char* name) : stream_(obj->stream_) { stream_->OpenObject(name); } explicit JSONObject(const JSONArray* arr); ~JSONObject() { stream_->CloseObject(); } void AddServiceId(const Object& o) const { stream_->PrintServiceId(o); } void AddFixedServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3); void AddServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3); void AddLocation( const Script& script, TokenPosition token_pos, TokenPosition end_token_pos = TokenPosition::kNoSource) const; void AddLocation(const BreakpointLocation* bpt_loc) const; void AddUnresolvedLocation(const BreakpointLocation* bpt_loc) const; void AddProperty(const char* name, bool b) const { stream_->PrintPropertyBool(name, b); } void AddProperty(const char* name, intptr_t i) const { stream_->PrintProperty(name, i); } void AddProperty64(const char* name, int64_t i) const { stream_->PrintProperty64(name, i); } void AddPropertyTimeMillis(const char* name, int64_t millis) const { stream_->PrintPropertyTimeMillis(name, millis); } void AddPropertyTimeMicros(const char* name, int64_t micros) const { stream_->PrintPropertyTimeMicros(name, micros); } void AddProperty(const char* name, double d) const { stream_->PrintProperty(name, d); } void AddPropertyBase64(const char* name, const uint8_t* bytes, intptr_t length) const { stream_->PrintPropertyBase64(name, bytes, length); } void AddProperty(const char* name, const char* s) const { stream_->PrintProperty(name, s); } bool AddPropertyStr(const char* name, const String& s, intptr_t offset = 0, intptr_t count = -1) const { return stream_->PrintPropertyStr(name, s, offset, count); } void AddPropertyNoEscape(const char* name, const char* s) const { stream_->PrintPropertyNoEscape(name, s); } void AddProperty(const char* name, const Object& obj, bool ref = true) const { stream_->PrintProperty(name, obj, ref); } void AddProperty(const char* name, const ServiceEvent* event) const { stream_->PrintProperty(name, event); } void AddProperty(const char* name, Breakpoint* bpt) const { stream_->PrintProperty(name, bpt); } void AddProperty(const char* name, TokenPosition tp) const { stream_->PrintProperty(name, tp); } void AddProperty(const char* name, Metric* metric) const { stream_->PrintProperty(name, metric); } void AddProperty(const char* name, MessageQueue* queue) const { stream_->PrintProperty(name, queue); } void AddProperty(const char* name, Isolate* isolate) const { stream_->PrintProperty(name, isolate); } void AddProperty(const char* name, Zone* zone) const { stream_->PrintProperty(name, zone); } void AddProperty(const char* name, const TimelineEvent* timeline_event) const { stream_->PrintProperty(name, timeline_event); } void AddProperty(const char* name, const TimelineEventBlock* timeline_event_block) const { stream_->PrintProperty(name, timeline_event_block); } void AddPropertyVM(const char* name, bool ref = true) const { stream_->PrintPropertyVM(name, ref); } void AddPropertyF(const char* name, const char* format, ...) const PRINTF_ATTRIBUTE(3, 4); private: JSONStream* stream_; friend class JSONArray; DISALLOW_ALLOCATION(); DISALLOW_COPY_AND_ASSIGN(JSONObject); }; class JSONArray : public ValueObject { public: explicit JSONArray(JSONStream* stream) : stream_(stream) { stream_->OpenArray(); } JSONArray(const JSONObject* obj, const char* name) : stream_(obj->stream_) { stream_->OpenArray(name); } explicit JSONArray(const JSONArray* arr) : stream_(arr->stream_) { stream_->OpenArray(); } ~JSONArray() { stream_->CloseArray(); } void AddValueNull() const { stream_->PrintValueNull(); } void AddValue(bool b) const { stream_->PrintValueBool(b); } void AddValue(intptr_t i) const { stream_->PrintValue(i); } void AddValue64(int64_t i) const { stream_->PrintValue64(i); } void AddValueTimeMillis(int64_t millis) const { stream_->PrintValueTimeMillis(millis); } void AddValueTimeMicros(int64_t micros) const { stream_->PrintValueTimeMicros(micros); } void AddValue(double d) const { stream_->PrintValue(d); } void AddValue(const char* s) const { stream_->PrintValue(s); } void AddValue(const Object& obj, bool ref = true) const { stream_->PrintValue(obj, ref); } void AddValue(Isolate* isolate, bool ref = true) const { stream_->PrintValue(isolate, ref); } void AddValue(IsolateGroup* isolate_group, bool ref = true) const { stream_->PrintValue(isolate_group, ref); } void AddValue(Breakpoint* bpt) const { stream_->PrintValue(bpt); } void AddValue(TokenPosition tp) const { stream_->PrintValue(tp); } void AddValue(const ServiceEvent* event) const { stream_->PrintValue(event); } void AddValue(Metric* metric) const { stream_->PrintValue(metric); } void AddValue(MessageQueue* queue) const { stream_->PrintValue(queue); } void AddValue(const TimelineEvent* timeline_event) const { stream_->PrintValue(timeline_event); } void AddValue(const TimelineEventBlock* timeline_event_block) const { stream_->PrintValue(timeline_event_block); } void AddValueVM(bool ref = true) const { stream_->PrintValueVM(ref); } void AddValueF(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3); private: JSONStream* stream_; friend class JSONObject; DISALLOW_ALLOCATION(); DISALLOW_COPY_AND_ASSIGN(JSONArray); }; } // namespace dart #endif // RUNTIME_VM_JSON_STREAM_H_