1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #ifndef RUNTIME_VM_JSON_STREAM_H_ |
6 | #define RUNTIME_VM_JSON_STREAM_H_ |
7 | |
8 | #include "include/dart_api.h" // for Dart_Port |
9 | #include "platform/allocation.h" |
10 | #include "platform/text_buffer.h" |
11 | #include "vm/json_writer.h" |
12 | #include "vm/service.h" |
13 | #include "vm/token_position.h" |
14 | |
15 | namespace dart { |
16 | |
17 | class Array; |
18 | class Breakpoint; |
19 | class BreakpointLocation; |
20 | class Field; |
21 | class GrowableObjectArray; |
22 | class Instance; |
23 | class JSONArray; |
24 | class JSONObject; |
25 | class MessageQueue; |
26 | class Metric; |
27 | class Object; |
28 | class Script; |
29 | class ServiceEvent; |
30 | class String; |
31 | class TimelineEvent; |
32 | class TimelineEventBlock; |
33 | class Thread; |
34 | class ThreadRegistry; |
35 | class Zone; |
36 | |
37 | // Keep this enum in sync with: |
38 | // |
39 | // - runtime/vm/service/vmservice.dart |
40 | // - runtime/observatory/lib/src/service/object.dart |
41 | // - pkg/dds/lib/src/rpc_error_codes.dart |
42 | // |
43 | enum JSONRpcErrorCode { |
44 | kParseError = -32700, |
45 | kInvalidRequest = -32600, |
46 | kMethodNotFound = -32601, |
47 | kInvalidParams = -32602, |
48 | kInternalError = -32603, |
49 | |
50 | kExtensionError = -32000, |
51 | |
52 | kFeatureDisabled = 100, |
53 | kCannotAddBreakpoint = 102, |
54 | kStreamAlreadySubscribed = 103, |
55 | kStreamNotSubscribed = 104, |
56 | kIsolateMustBeRunnable = 105, |
57 | kIsolateMustBePaused = 106, |
58 | kCannotResume = 107, |
59 | kIsolateIsReloading = 108, |
60 | kIsolateReloadBarred = 109, |
61 | kIsolateMustHaveReloaded = 110, |
62 | kServiceAlreadyRegistered = 111, |
63 | kServiceDisappeared = 112, |
64 | kExpressionCompilationError = 113, |
65 | kInvalidTimelineRequest = 114, |
66 | |
67 | // Experimental (used in private rpcs). |
68 | kFileSystemAlreadyExists = 1001, |
69 | kFileSystemDoesNotExist = 1002, |
70 | kFileDoesNotExist = 1003, |
71 | }; |
72 | |
73 | // Builds on JSONWriter to provide support for serializing various objects |
74 | // used in the VM service protocol. |
75 | class JSONStream : ValueObject { |
76 | public: |
77 | explicit JSONStream(intptr_t buf_size = 256); |
78 | |
79 | void Setup(Zone* zone, |
80 | Dart_Port reply_port, |
81 | const Instance& seq, |
82 | const String& method, |
83 | const Array& param_keys, |
84 | const Array& param_values, |
85 | bool parameters_are_dart_objects = false); |
86 | void SetupError(); |
87 | |
88 | void PrintError(intptr_t code, const char* details_format, ...) |
89 | PRINTF_ATTRIBUTE(3, 4); |
90 | |
91 | void PostReply(); |
92 | |
93 | void set_id_zone(ServiceIdZone* id_zone) { id_zone_ = id_zone; } |
94 | ServiceIdZone* id_zone() { return id_zone_; } |
95 | |
96 | TextBuffer* buffer() { return writer_.buffer(); } |
97 | const char* ToCString() { return writer_.ToCString(); } |
98 | |
99 | void Steal(char** buffer, intptr_t* buffer_length) { |
100 | writer_.Steal(buffer, buffer_length); |
101 | } |
102 | |
103 | void set_reply_port(Dart_Port port); |
104 | |
105 | void SetParams(const char** param_keys, |
106 | const char** param_values, |
107 | intptr_t num_params); |
108 | |
109 | Dart_Port reply_port() const { return reply_port_; } |
110 | |
111 | intptr_t NumObjectParameters() const; |
112 | ObjectPtr GetObjectParameterKey(intptr_t i) const; |
113 | ObjectPtr GetObjectParameterValue(intptr_t i) const; |
114 | ObjectPtr LookupObjectParam(const char* key) const; |
115 | |
116 | intptr_t num_params() const { return num_params_; } |
117 | const char* GetParamKey(intptr_t i) const { return param_keys_[i]; } |
118 | const char* GetParamValue(intptr_t i) const { return param_values_[i]; } |
119 | |
120 | const char* LookupParam(const char* key) const; |
121 | |
122 | bool HasParam(const char* key) const; |
123 | |
124 | // Returns true if there is an param with key and value, false |
125 | // otherwise. |
126 | bool ParamIs(const char* key, const char* value) const; |
127 | |
128 | const char* method() const { return method_; } |
129 | const char** param_keys() const { return param_keys_; } |
130 | const char** param_values() const { return param_values_; } |
131 | |
132 | void set_offset(intptr_t value) { |
133 | ASSERT(value > 0); |
134 | offset_ = value; |
135 | } |
136 | |
137 | void set_count(intptr_t value) { |
138 | ASSERT(value > 0); |
139 | count_ = value; |
140 | } |
141 | |
142 | void ComputeOffsetAndCount(intptr_t length, |
143 | intptr_t* offset, |
144 | intptr_t* count); |
145 | |
146 | // Append |serialized_object| to the stream. |
147 | void AppendSerializedObject(const char* serialized_object) { |
148 | writer_.AppendSerializedObject(serialized_object); |
149 | } |
150 | |
151 | // Append |buffer| to the stream. |
152 | void AppendSerializedObject(const uint8_t* buffer, intptr_t buffer_length) { |
153 | writer_.AppendSerializedObject(buffer, buffer_length); |
154 | } |
155 | |
156 | // Append |serialized_object| to the stream with |property_name|. |
157 | void AppendSerializedObject(const char* property_name, |
158 | const char* serialized_object) { |
159 | writer_.AppendSerializedObject(property_name, serialized_object); |
160 | } |
161 | |
162 | void PrintCommaIfNeeded() { writer_.PrintCommaIfNeeded(); } |
163 | |
164 | private: |
165 | void Clear() { writer_.Clear(); } |
166 | |
167 | void PostNullReply(Dart_Port port); |
168 | |
169 | void OpenObject(const char* property_name = NULL) { |
170 | writer_.OpenObject(property_name); |
171 | } |
172 | void CloseObject() { writer_.CloseObject(); } |
173 | void UncloseObject() { writer_.UncloseObject(); } |
174 | |
175 | void OpenArray(const char* property_name = NULL) { |
176 | writer_.OpenArray(property_name); |
177 | } |
178 | void CloseArray() { writer_.CloseArray(); } |
179 | |
180 | void PrintValueNull() { writer_.PrintValueNull(); } |
181 | void PrintValueBool(bool b) { writer_.PrintValueBool(b); } |
182 | void PrintValue(intptr_t i) { writer_.PrintValue(i); } |
183 | void PrintValue64(int64_t i) { writer_.PrintValue64(i); } |
184 | void PrintValueTimeMillis(int64_t millis) { writer_.PrintValue64(millis); } |
185 | void PrintValueTimeMicros(int64_t micros) { writer_.PrintValue64(micros); } |
186 | void PrintValue(double d) { writer_.PrintValue(d); } |
187 | void PrintValueBase64(const uint8_t* bytes, intptr_t length) { |
188 | writer_.PrintValueBase64(bytes, length); |
189 | } |
190 | void PrintValue(const char* s) { writer_.PrintValue(s); } |
191 | void PrintValueNoEscape(const char* s) { writer_.PrintValueNoEscape(s); } |
192 | bool PrintValueStr(const String& s, intptr_t offset, intptr_t count) { |
193 | return writer_.PrintValueStr(s, offset, count); |
194 | } |
195 | void PrintfValue(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
196 | void VPrintfValue(const char* format, va_list args) { |
197 | writer_.VPrintfValue(format, args); |
198 | } |
199 | |
200 | void PrintValue(const Object& o, bool ref = true); |
201 | void PrintValue(Breakpoint* bpt); |
202 | void PrintValue(TokenPosition tp); |
203 | void PrintValue(const ServiceEvent* event); |
204 | void PrintValue(Metric* metric); |
205 | void PrintValue(MessageQueue* queue); |
206 | void PrintValue(Isolate* isolate, bool ref = true); |
207 | void PrintValue(IsolateGroup* isolate, bool ref = true); |
208 | void PrintValue(ThreadRegistry* reg); |
209 | void PrintValue(Thread* thread); |
210 | void PrintValue(const TimelineEvent* timeline_event); |
211 | void PrintValue(const TimelineEventBlock* timeline_event_block); |
212 | void PrintValueVM(bool ref = true); |
213 | |
214 | void PrintServiceId(const Object& o); |
215 | |
216 | void PrintPropertyBool(const char* name, bool b) { |
217 | writer_.PrintPropertyBool(name, b); |
218 | } |
219 | void PrintProperty(const char* name, intptr_t i) { |
220 | writer_.PrintProperty(name, i); |
221 | } |
222 | void PrintProperty64(const char* name, int64_t i) { |
223 | writer_.PrintProperty64(name, i); |
224 | } |
225 | void PrintPropertyTimeMillis(const char* name, int64_t millis) { |
226 | writer_.PrintProperty64(name, millis); |
227 | } |
228 | void PrintPropertyTimeMicros(const char* name, int64_t micros) { |
229 | writer_.PrintProperty64(name, micros); |
230 | } |
231 | void PrintProperty(const char* name, double d) { |
232 | writer_.PrintProperty(name, d); |
233 | } |
234 | void PrintPropertyBase64(const char* name, |
235 | const uint8_t* bytes, |
236 | intptr_t length) { |
237 | writer_.PrintPropertyBase64(name, bytes, length); |
238 | } |
239 | void PrintProperty(const char* name, const char* s) { |
240 | writer_.PrintProperty(name, s); |
241 | } |
242 | bool PrintPropertyStr(const char* name, |
243 | const String& s, |
244 | intptr_t offset, |
245 | intptr_t count) { |
246 | return writer_.PrintPropertyStr(name, s, offset, count); |
247 | } |
248 | void PrintPropertyNoEscape(const char* name, const char* s) { |
249 | writer_.PrintPropertyNoEscape(name, s); |
250 | } |
251 | void PrintfProperty(const char* name, const char* format, ...) |
252 | PRINTF_ATTRIBUTE(3, 4); |
253 | void VPrintfProperty(const char* name, const char* format, va_list args) { |
254 | writer_.VPrintfProperty(name, format, args); |
255 | } |
256 | void PrintProperty(const char* name, const Object& o, bool ref = true); |
257 | |
258 | void PrintProperty(const char* name, const ServiceEvent* event); |
259 | void PrintProperty(const char* name, Breakpoint* bpt); |
260 | void PrintProperty(const char* name, TokenPosition tp); |
261 | void PrintProperty(const char* name, Metric* metric); |
262 | void PrintProperty(const char* name, MessageQueue* queue); |
263 | void PrintProperty(const char* name, Isolate* isolate); |
264 | void PrintProperty(const char* name, ThreadRegistry* reg); |
265 | void PrintProperty(const char* name, Thread* thread); |
266 | void PrintProperty(const char* name, Zone* zone); |
267 | void PrintProperty(const char* name, const TimelineEvent* timeline_event); |
268 | void PrintProperty(const char* name, |
269 | const TimelineEventBlock* timeline_event_block); |
270 | void PrintPropertyVM(const char* name, bool ref = true); |
271 | void PrintPropertyName(const char* name) { writer_.PrintPropertyName(name); } |
272 | |
273 | void AddEscapedUTF8String(const char* s, intptr_t len) { |
274 | writer_.AddEscapedUTF8String(s, len); |
275 | } |
276 | |
277 | JSONWriter writer_; |
278 | // Default service id zone. |
279 | RingServiceIdZone default_id_zone_; |
280 | ServiceIdZone* id_zone_; |
281 | Dart_Port reply_port_; |
282 | Instance* seq_; |
283 | Array* parameter_keys_; |
284 | Array* parameter_values_; |
285 | const char* method_; |
286 | const char** param_keys_; |
287 | const char** param_values_; |
288 | intptr_t num_params_; |
289 | intptr_t offset_; |
290 | intptr_t count_; |
291 | int64_t setup_time_micros_; |
292 | |
293 | friend class JSONObject; |
294 | friend class JSONArray; |
295 | friend class TimelineEvent; |
296 | }; |
297 | |
298 | class JSONObject : public ValueObject { |
299 | public: |
300 | explicit JSONObject(JSONStream* stream) : stream_(stream) { |
301 | stream_->OpenObject(); |
302 | } |
303 | JSONObject(const JSONObject* obj, const char* name) : stream_(obj->stream_) { |
304 | stream_->OpenObject(name); |
305 | } |
306 | explicit JSONObject(const JSONArray* arr); |
307 | |
308 | ~JSONObject() { stream_->CloseObject(); } |
309 | |
310 | void AddServiceId(const Object& o) const { stream_->PrintServiceId(o); } |
311 | |
312 | void AddFixedServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3); |
313 | void AddServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3); |
314 | |
315 | void AddLocation( |
316 | const Script& script, |
317 | TokenPosition token_pos, |
318 | TokenPosition end_token_pos = TokenPosition::kNoSource) const; |
319 | |
320 | void AddLocation(const BreakpointLocation* bpt_loc) const; |
321 | |
322 | void AddUnresolvedLocation(const BreakpointLocation* bpt_loc) const; |
323 | |
324 | void AddProperty(const char* name, bool b) const { |
325 | stream_->PrintPropertyBool(name, b); |
326 | } |
327 | void AddProperty(const char* name, intptr_t i) const { |
328 | stream_->PrintProperty(name, i); |
329 | } |
330 | void AddProperty64(const char* name, int64_t i) const { |
331 | stream_->PrintProperty64(name, i); |
332 | } |
333 | void AddPropertyTimeMillis(const char* name, int64_t millis) const { |
334 | stream_->PrintPropertyTimeMillis(name, millis); |
335 | } |
336 | void AddPropertyTimeMicros(const char* name, int64_t micros) const { |
337 | stream_->PrintPropertyTimeMicros(name, micros); |
338 | } |
339 | void AddProperty(const char* name, double d) const { |
340 | stream_->PrintProperty(name, d); |
341 | } |
342 | void AddPropertyBase64(const char* name, |
343 | const uint8_t* bytes, |
344 | intptr_t length) const { |
345 | stream_->PrintPropertyBase64(name, bytes, length); |
346 | } |
347 | void AddProperty(const char* name, const char* s) const { |
348 | stream_->PrintProperty(name, s); |
349 | } |
350 | bool AddPropertyStr(const char* name, |
351 | const String& s, |
352 | intptr_t offset = 0, |
353 | intptr_t count = -1) const { |
354 | return stream_->PrintPropertyStr(name, s, offset, count); |
355 | } |
356 | void AddPropertyNoEscape(const char* name, const char* s) const { |
357 | stream_->PrintPropertyNoEscape(name, s); |
358 | } |
359 | void AddProperty(const char* name, const Object& obj, bool ref = true) const { |
360 | stream_->PrintProperty(name, obj, ref); |
361 | } |
362 | void AddProperty(const char* name, const ServiceEvent* event) const { |
363 | stream_->PrintProperty(name, event); |
364 | } |
365 | void AddProperty(const char* name, Breakpoint* bpt) const { |
366 | stream_->PrintProperty(name, bpt); |
367 | } |
368 | void AddProperty(const char* name, TokenPosition tp) const { |
369 | stream_->PrintProperty(name, tp); |
370 | } |
371 | void AddProperty(const char* name, Metric* metric) const { |
372 | stream_->PrintProperty(name, metric); |
373 | } |
374 | void AddProperty(const char* name, MessageQueue* queue) const { |
375 | stream_->PrintProperty(name, queue); |
376 | } |
377 | void AddProperty(const char* name, Isolate* isolate) const { |
378 | stream_->PrintProperty(name, isolate); |
379 | } |
380 | void AddProperty(const char* name, ThreadRegistry* reg) const { |
381 | stream_->PrintProperty(name, reg); |
382 | } |
383 | void AddProperty(const char* name, Thread* thread) const { |
384 | stream_->PrintProperty(name, thread); |
385 | } |
386 | void AddProperty(const char* name, Zone* zone) const { |
387 | stream_->PrintProperty(name, zone); |
388 | } |
389 | void AddProperty(const char* name, |
390 | const TimelineEvent* timeline_event) const { |
391 | stream_->PrintProperty(name, timeline_event); |
392 | } |
393 | void AddProperty(const char* name, |
394 | const TimelineEventBlock* timeline_event_block) const { |
395 | stream_->PrintProperty(name, timeline_event_block); |
396 | } |
397 | void AddPropertyVM(const char* name, bool ref = true) const { |
398 | stream_->PrintPropertyVM(name, ref); |
399 | } |
400 | void AddPropertyF(const char* name, const char* format, ...) const |
401 | PRINTF_ATTRIBUTE(3, 4); |
402 | |
403 | private: |
404 | JSONStream* stream_; |
405 | |
406 | friend class JSONArray; |
407 | |
408 | DISALLOW_ALLOCATION(); |
409 | DISALLOW_COPY_AND_ASSIGN(JSONObject); |
410 | }; |
411 | |
412 | class JSONArray : public ValueObject { |
413 | public: |
414 | explicit JSONArray(JSONStream* stream) : stream_(stream) { |
415 | stream_->OpenArray(); |
416 | } |
417 | JSONArray(const JSONObject* obj, const char* name) : stream_(obj->stream_) { |
418 | stream_->OpenArray(name); |
419 | } |
420 | explicit JSONArray(const JSONArray* arr) : stream_(arr->stream_) { |
421 | stream_->OpenArray(); |
422 | } |
423 | ~JSONArray() { stream_->CloseArray(); } |
424 | |
425 | void AddValueNull() const { stream_->PrintValueNull(); } |
426 | void AddValue(bool b) const { stream_->PrintValueBool(b); } |
427 | void AddValue(intptr_t i) const { stream_->PrintValue(i); } |
428 | void AddValue64(int64_t i) const { stream_->PrintValue64(i); } |
429 | void AddValueTimeMillis(int64_t millis) const { |
430 | stream_->PrintValueTimeMillis(millis); |
431 | } |
432 | void AddValueTimeMicros(int64_t micros) const { |
433 | stream_->PrintValueTimeMicros(micros); |
434 | } |
435 | void AddValue(double d) const { stream_->PrintValue(d); } |
436 | void AddValue(const char* s) const { stream_->PrintValue(s); } |
437 | void AddValue(const Object& obj, bool ref = true) const { |
438 | stream_->PrintValue(obj, ref); |
439 | } |
440 | void AddValue(Isolate* isolate, bool ref = true) const { |
441 | stream_->PrintValue(isolate, ref); |
442 | } |
443 | void AddValue(IsolateGroup* isolate_group, bool ref = true) const { |
444 | stream_->PrintValue(isolate_group, ref); |
445 | } |
446 | void AddValue(ThreadRegistry* reg) const { stream_->PrintValue(reg); } |
447 | void AddValue(Thread* thread) const { stream_->PrintValue(thread); } |
448 | void AddValue(Breakpoint* bpt) const { stream_->PrintValue(bpt); } |
449 | void AddValue(TokenPosition tp) const { stream_->PrintValue(tp); } |
450 | void AddValue(const ServiceEvent* event) const { stream_->PrintValue(event); } |
451 | void AddValue(Metric* metric) const { stream_->PrintValue(metric); } |
452 | void AddValue(MessageQueue* queue) const { stream_->PrintValue(queue); } |
453 | void AddValue(const TimelineEvent* timeline_event) const { |
454 | stream_->PrintValue(timeline_event); |
455 | } |
456 | void AddValue(const TimelineEventBlock* timeline_event_block) const { |
457 | stream_->PrintValue(timeline_event_block); |
458 | } |
459 | void AddValueVM(bool ref = true) const { stream_->PrintValueVM(ref); } |
460 | void AddValueF(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3); |
461 | |
462 | private: |
463 | JSONStream* stream_; |
464 | |
465 | friend class JSONObject; |
466 | |
467 | DISALLOW_ALLOCATION(); |
468 | DISALLOW_COPY_AND_ASSIGN(JSONArray); |
469 | }; |
470 | |
471 | } // namespace dart |
472 | |
473 | #endif // RUNTIME_VM_JSON_STREAM_H_ |
474 | |