text.pretty: create an event string instead of using fprintf()/fputs()
[babeltrace.git] / plugins / text / pretty / print.c
1 /*
2 * print.c
3 *
4 * Babeltrace CTF Text Output Plugin Event Printing
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30 #include <babeltrace/ctf-ir/event.h>
31 #include <babeltrace/ctf-ir/event-class.h>
32 #include <babeltrace/ctf-ir/packet.h>
33 #include <babeltrace/ctf-ir/stream.h>
34 #include <babeltrace/ctf-ir/stream-class.h>
35 #include <babeltrace/ctf-ir/clock-class.h>
36 #include <babeltrace/ctf-ir/field-types.h>
37 #include <babeltrace/ctf-ir/fields.h>
38 #include <babeltrace/ctf-ir/trace.h>
39 #include <babeltrace/graph/notification-event.h>
40 #include <babeltrace/graph/clock-class-priority-map.h>
41 #include <babeltrace/bitfield-internal.h>
42 #include <babeltrace/common-internal.h>
43 #include <inttypes.h>
44 #include <ctype.h>
45 #include "pretty.h"
46
47 #define NSEC_PER_SEC 1000000000LL
48
49 #define COLOR_NAME BT_COMMON_COLOR_BOLD
50 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
51 #define COLOR_RST BT_COMMON_COLOR_RESET
52 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
53 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
54 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
55 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
56 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
57 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
58
59 static inline
60 const char *rem_(const char *str)
61 {
62 if (str[0] == '_')
63 return &str[1];
64 else
65 return str;
66 }
67
68 struct timestamp {
69 int64_t real_timestamp; /* Relative to UNIX epoch. */
70 uint64_t clock_value; /* In cycles. */
71 };
72
73 static
74 enum bt_component_status print_field(struct pretty_component *pretty,
75 struct bt_ctf_field *field, bool print_names,
76 GQuark *filters_fields, int filter_array_len);
77
78 static
79 void print_name_equal(struct pretty_component *pretty, const char *name)
80 {
81 if (pretty->use_colors) {
82 g_string_append_printf(pretty->string, "%s%s%s = ", COLOR_NAME,
83 name, COLOR_RST);
84 } else {
85 g_string_append_printf(pretty->string, "%s = ", name);
86 }
87 }
88
89 static
90 void print_field_name_equal(struct pretty_component *pretty, const char *name)
91 {
92 if (pretty->use_colors) {
93 g_string_append_printf(pretty->string, "%s%s%s = ",
94 COLOR_FIELD_NAME, name, COLOR_RST);
95 } else {
96 g_string_append_printf(pretty->string, "%s = ", name);
97 }
98 }
99
100 static
101 void print_timestamp_cycles(struct pretty_component *pretty,
102 struct bt_ctf_clock_class *clock_class,
103 struct bt_ctf_event *event)
104 {
105 int ret;
106 struct bt_ctf_clock_value *clock_value;
107 uint64_t cycles;
108
109 clock_value = bt_ctf_event_get_clock_value(event, clock_class);
110 if (!clock_value) {
111 g_string_append(pretty->string, "????????????????????");
112 return;
113 }
114
115 ret = bt_ctf_clock_value_get_value(clock_value, &cycles);
116 bt_put(clock_value);
117 if (ret) {
118 // TODO: log, this is unexpected
119 g_string_append(pretty->string, "Error");
120 return;
121 }
122
123 g_string_append_printf(pretty->string, "%020" PRIu64, cycles);
124
125 if (pretty->last_cycles_timestamp != -1ULL) {
126 pretty->delta_cycles = cycles - pretty->last_cycles_timestamp;
127 }
128 pretty->last_cycles_timestamp = cycles;
129 }
130
131 static
132 void print_timestamp_wall(struct pretty_component *pretty,
133 struct bt_ctf_clock_class *clock_class,
134 struct bt_ctf_event *event)
135 {
136 int ret;
137 struct bt_ctf_clock_value *clock_value;
138 int64_t ts_nsec = 0; /* add configurable offset */
139 int64_t ts_sec = 0; /* add configurable offset */
140 uint64_t ts_sec_abs, ts_nsec_abs;
141 bool is_negative;
142
143 clock_value = bt_ctf_event_get_clock_value(event, clock_class);
144 if (!clock_value) {
145 g_string_append(pretty->string, "??:??:??.?????????");
146 return;
147 }
148
149 ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec);
150 bt_put(clock_value);
151 if (ret) {
152 // TODO: log, this is unexpected
153 g_string_append(pretty->string, "Error");
154 return;
155 }
156
157 if (pretty->last_real_timestamp != -1ULL) {
158 pretty->delta_real_timestamp = ts_nsec - pretty->last_real_timestamp;
159 }
160
161 pretty->last_real_timestamp = ts_nsec;
162 ts_sec += ts_nsec / NSEC_PER_SEC;
163 ts_nsec = ts_nsec % NSEC_PER_SEC;
164
165 if (ts_sec >= 0 && ts_nsec >= 0) {
166 is_negative = false;
167 ts_sec_abs = ts_sec;
168 ts_nsec_abs = ts_nsec;
169 } else if (ts_sec > 0 && ts_nsec < 0) {
170 is_negative = false;
171 ts_sec_abs = ts_sec - 1;
172 ts_nsec_abs = NSEC_PER_SEC + ts_nsec;
173 } else if (ts_sec == 0 && ts_nsec < 0) {
174 is_negative = true;
175 ts_sec_abs = ts_sec;
176 ts_nsec_abs = -ts_nsec;
177 } else if (ts_sec < 0 && ts_nsec > 0) {
178 is_negative = true;
179 ts_sec_abs = -(ts_sec + 1);
180 ts_nsec_abs = NSEC_PER_SEC - ts_nsec;
181 } else if (ts_sec < 0 && ts_nsec == 0) {
182 is_negative = true;
183 ts_sec_abs = -ts_sec;
184 ts_nsec_abs = ts_nsec;
185 } else { /* (ts_sec < 0 && ts_nsec < 0) */
186 is_negative = true;
187 ts_sec_abs = -ts_sec;
188 ts_nsec_abs = -ts_nsec;
189 }
190
191 if (!pretty->options.clock_seconds) {
192 struct tm tm;
193 time_t time_s = (time_t) ts_sec_abs;
194
195 if (is_negative) {
196 // TODO: log instead
197 fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
198 goto seconds;
199 }
200
201 if (!pretty->options.clock_gmt) {
202 struct tm *res;
203
204 res = localtime_r(&time_s, &tm);
205 if (!res) {
206 // TODO: log instead
207 fprintf(stderr, "[warning] Unable to get localtime.\n");
208 goto seconds;
209 }
210 } else {
211 struct tm *res;
212
213 res = gmtime_r(&time_s, &tm);
214 if (!res) {
215 // TODO: log instead
216 fprintf(stderr, "[warning] Unable to get gmtime.\n");
217 goto seconds;
218 }
219 }
220 if (pretty->options.clock_date) {
221 char timestr[26];
222 size_t res;
223
224 /* Print date and time */
225 res = strftime(timestr, sizeof(timestr),
226 "%F ", &tm);
227 if (!res) {
228 // TODO: log instead
229 fprintf(stderr, "[warning] Unable to print ascii time.\n");
230 goto seconds;
231 }
232
233 g_string_append(pretty->string, timestr);
234 }
235
236 /* Print time in HH:MM:SS.ns */
237 g_string_append_printf(pretty->string,
238 "%02d:%02d:%02d.%09" PRIu64, tm.tm_hour, tm.tm_min,
239 tm.tm_sec, ts_nsec_abs);
240 goto end;
241 }
242 seconds:
243 g_string_append_printf(pretty->string, "%s%" PRId64 ".%09" PRIu64,
244 is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs);
245 end:
246 return;
247 }
248
249 static
250 enum bt_component_status print_event_timestamp(struct pretty_component *pretty,
251 struct bt_ctf_event *event,
252 struct bt_clock_class_priority_map *cc_prio_map,
253 bool *start_line)
254 {
255 bool print_names = pretty->options.print_header_field_names;
256 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
257 struct bt_ctf_stream *stream = NULL;
258 struct bt_ctf_stream_class *stream_class = NULL;
259 struct bt_ctf_trace *trace = NULL;
260 struct bt_ctf_clock_class *clock_class = NULL;
261
262 stream = bt_ctf_event_get_stream(event);
263 if (!stream) {
264 ret = BT_COMPONENT_STATUS_ERROR;
265 goto end;
266 }
267
268 stream_class = bt_ctf_stream_get_class(stream);
269 if (!stream_class) {
270 ret = BT_COMPONENT_STATUS_ERROR;
271 goto end;
272 }
273 trace = bt_ctf_stream_class_get_trace(stream_class);
274 if (!trace) {
275 ret = BT_COMPONENT_STATUS_ERROR;
276 goto end;
277 }
278
279 if (bt_clock_class_priority_map_get_clock_class_count(cc_prio_map) == 0) {
280 /* No clock class: skip the timestamp without an error */
281 goto end;
282 }
283
284 clock_class =
285 bt_clock_class_priority_map_get_highest_priority_clock_class(
286 cc_prio_map);
287 if (!clock_class) {
288 ret = BT_COMPONENT_STATUS_ERROR;
289 goto end;
290 }
291
292 if (print_names) {
293 print_name_equal(pretty, "timestamp");
294 } else {
295 g_string_append(pretty->string, "[");
296 }
297 if (pretty->use_colors) {
298 g_string_append(pretty->string, COLOR_TIMESTAMP);
299 }
300 if (pretty->options.print_timestamp_cycles) {
301 print_timestamp_cycles(pretty, clock_class, event);
302 } else {
303 print_timestamp_wall(pretty, clock_class, event);
304 }
305 if (pretty->use_colors) {
306 g_string_append(pretty->string, COLOR_RST);
307 }
308
309 if (!print_names)
310 g_string_append(pretty->string, "] ");
311
312 if (pretty->options.print_delta_field) {
313 if (print_names) {
314 g_string_append(pretty->string, ", ");
315 print_name_equal(pretty, "delta");
316 } else {
317 g_string_append(pretty->string, "(");
318 }
319 if (pretty->options.print_timestamp_cycles) {
320 if (pretty->delta_cycles == -1ULL) {
321 g_string_append(pretty->string,
322 "+??????????\?\?) "); /* Not a trigraph. */
323 } else {
324 g_string_append_printf(pretty->string,
325 "+%012" PRIu64, pretty->delta_cycles);
326 }
327 } else {
328 if (pretty->delta_real_timestamp != -1ULL) {
329 uint64_t delta_sec, delta_nsec, delta;
330
331 delta = pretty->delta_real_timestamp;
332 delta_sec = delta / NSEC_PER_SEC;
333 delta_nsec = delta % NSEC_PER_SEC;
334 g_string_append_printf(pretty->string,
335 "+%" PRIu64 ".%09" PRIu64,
336 delta_sec, delta_nsec);
337 } else {
338 g_string_append(pretty->string, "+?.?????????");
339 }
340 }
341 if (!print_names) {
342 g_string_append(pretty->string, ") ");
343 }
344 }
345 *start_line = !print_names;
346
347 end:
348 bt_put(stream);
349 bt_put(clock_class);
350 bt_put(stream_class);
351 bt_put(trace);
352 return ret;
353 }
354
355 static
356 enum bt_component_status print_event_header(struct pretty_component *pretty,
357 struct bt_ctf_event *event,
358 struct bt_clock_class_priority_map *cc_prio_map)
359 {
360 bool print_names = pretty->options.print_header_field_names;
361 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
362 struct bt_ctf_event_class *event_class = NULL;
363 struct bt_ctf_stream_class *stream_class = NULL;
364 struct bt_ctf_trace *trace_class = NULL;
365 int dom_print = 0;
366
367 event_class = bt_ctf_event_get_class(event);
368 if (!event_class) {
369 ret = BT_COMPONENT_STATUS_ERROR;
370 goto end;
371 }
372 stream_class = bt_ctf_event_class_get_stream_class(event_class);
373 if (!stream_class) {
374 ret = BT_COMPONENT_STATUS_ERROR;
375 goto end;
376 }
377 trace_class = bt_ctf_stream_class_get_trace(stream_class);
378 if (!trace_class) {
379 ret = BT_COMPONENT_STATUS_ERROR;
380 goto end;
381 }
382 ret = print_event_timestamp(pretty, event, cc_prio_map,
383 &pretty->start_line);
384 if (ret != BT_COMPONENT_STATUS_OK) {
385 goto end;
386 }
387 if (pretty->options.print_trace_field) {
388 const char *name;
389
390 name = bt_ctf_trace_get_name(trace_class);
391 if (name) {
392 if (!pretty->start_line) {
393 g_string_append(pretty->string, ", ");
394 }
395 if (print_names) {
396 print_name_equal(pretty, "trace");
397 }
398
399 g_string_append(pretty->string, name);
400
401 if (!print_names) {
402 g_string_append(pretty->string, " ");
403 }
404 }
405 }
406 if (pretty->options.print_trace_hostname_field) {
407 struct bt_value *hostname_str;
408
409 hostname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
410 "hostname");
411 if (hostname_str) {
412 const char *str;
413
414 if (!pretty->start_line) {
415 g_string_append(pretty->string, ", ");
416 }
417 if (print_names) {
418 print_name_equal(pretty, "trace:hostname");
419 }
420 if (bt_value_string_get(hostname_str, &str)
421 == BT_VALUE_STATUS_OK) {
422 g_string_append(pretty->string, str);
423 }
424 bt_put(hostname_str);
425 dom_print = 1;
426 }
427 }
428 if (pretty->options.print_trace_domain_field) {
429 struct bt_value *domain_str;
430
431 domain_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
432 "domain");
433 if (domain_str) {
434 const char *str;
435
436 if (!pretty->start_line) {
437 g_string_append(pretty->string, ", ");
438 }
439 if (print_names) {
440 print_name_equal(pretty, "trace:domain");
441 } else if (dom_print) {
442 g_string_append(pretty->string, ":");
443 }
444 if (bt_value_string_get(domain_str, &str)
445 == BT_VALUE_STATUS_OK) {
446 g_string_append(pretty->string, str);
447 }
448 bt_put(domain_str);
449 dom_print = 1;
450 }
451 }
452 if (pretty->options.print_trace_procname_field) {
453 struct bt_value *procname_str;
454
455 procname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
456 "procname");
457 if (procname_str) {
458 const char *str;
459
460 if (!pretty->start_line) {
461 g_string_append(pretty->string, ", ");
462 }
463 if (print_names) {
464 print_name_equal(pretty, "trace:procname");
465 } else if (dom_print) {
466 g_string_append(pretty->string, ":");
467 }
468 if (bt_value_string_get(procname_str, &str)
469 == BT_VALUE_STATUS_OK) {
470 g_string_append(pretty->string, str);
471 }
472 bt_put(procname_str);
473 dom_print = 1;
474 }
475 }
476 if (pretty->options.print_trace_vpid_field) {
477 struct bt_value *vpid_value;
478
479 vpid_value = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
480 "vpid");
481 if (vpid_value) {
482 int64_t value;
483
484 if (!pretty->start_line) {
485 g_string_append(pretty->string, ", ");
486 }
487 if (print_names) {
488 print_name_equal(pretty, "trace:vpid");
489 } else if (dom_print) {
490 g_string_append(pretty->string, ":");
491 }
492 if (bt_value_integer_get(vpid_value, &value)
493 == BT_VALUE_STATUS_OK) {
494 g_string_append_printf(pretty->string, "(%" PRId64 ")", value);
495 }
496 bt_put(vpid_value);
497 dom_print = 1;
498 }
499 }
500 if (pretty->options.print_loglevel_field) {
501 struct bt_value *loglevel_str, *loglevel_value;
502
503 loglevel_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
504 "loglevel_string");
505 loglevel_value = bt_ctf_event_class_get_attribute_value_by_name(event_class,
506 "loglevel");
507 if (loglevel_str || loglevel_value) {
508 bool has_str = false;
509
510 if (!pretty->start_line) {
511 g_string_append(pretty->string, ", ");
512 }
513 if (print_names) {
514 print_name_equal(pretty, "loglevel");
515 } else if (dom_print) {
516 g_string_append(pretty->string, ":");
517 }
518 if (loglevel_str) {
519 const char *str;
520
521 if (bt_value_string_get(loglevel_str, &str)
522 == BT_VALUE_STATUS_OK) {
523 g_string_append(pretty->string, str);
524 has_str = true;
525 }
526 }
527 if (loglevel_value) {
528 int64_t value;
529
530 if (bt_value_integer_get(loglevel_value, &value)
531 == BT_VALUE_STATUS_OK) {
532 g_string_append_printf(pretty->string, "%s(%" PRId64 ")",
533 has_str ? " " : "", value);
534 }
535 }
536 bt_put(loglevel_str);
537 bt_put(loglevel_value);
538 dom_print = 1;
539 }
540 }
541 if (pretty->options.print_emf_field) {
542 struct bt_value *uri_str;
543
544 uri_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
545 "model.emf.uri");
546 if (uri_str) {
547 if (!pretty->start_line) {
548 g_string_append(pretty->string, ", ");
549 }
550 if (print_names) {
551 print_name_equal(pretty, "model.emf.uri");
552 } else if (dom_print) {
553 g_string_append(pretty->string, ":");
554 }
555 if (uri_str) {
556 const char *str;
557
558 if (bt_value_string_get(uri_str, &str)
559 == BT_VALUE_STATUS_OK) {
560 g_string_append(pretty->string, str);
561 }
562 }
563 bt_put(uri_str);
564 dom_print = 1;
565 }
566 }
567 if (dom_print && !print_names) {
568 g_string_append(pretty->string, " ");
569 }
570 if (!pretty->start_line) {
571 g_string_append(pretty->string, ", ");
572 }
573 pretty->start_line = true;
574 if (print_names) {
575 print_name_equal(pretty, "name");
576 }
577 if (pretty->use_colors) {
578 g_string_append(pretty->string, COLOR_EVENT_NAME);
579 }
580 g_string_append(pretty->string, bt_ctf_event_class_get_name(event_class));
581 if (pretty->use_colors) {
582 g_string_append(pretty->string, COLOR_RST);
583 }
584 if (!print_names) {
585 g_string_append(pretty->string, ": ");
586 } else {
587 g_string_append(pretty->string, ", ");
588 }
589 end:
590 bt_put(trace_class);
591 bt_put(stream_class);
592 bt_put(event_class);
593 return ret;
594 }
595
596 static
597 enum bt_component_status print_integer(struct pretty_component *pretty,
598 struct bt_ctf_field *field)
599 {
600 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
601 struct bt_ctf_field_type *field_type = NULL;
602 enum bt_ctf_integer_base base;
603 enum bt_ctf_string_encoding encoding;
604 int signedness;
605 union {
606 uint64_t u;
607 int64_t s;
608 } v;
609 bool rst_color = false;
610
611 field_type = bt_ctf_field_get_type(field);
612 if (!field_type) {
613 ret = BT_COMPONENT_STATUS_ERROR;
614 goto end;
615 }
616 signedness = bt_ctf_field_type_integer_get_signed(field_type);
617 if (signedness < 0) {
618 ret = BT_COMPONENT_STATUS_ERROR;
619 goto end;
620 }
621 if (!signedness) {
622 if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) {
623 ret = BT_COMPONENT_STATUS_ERROR;
624 goto end;
625 }
626 } else {
627 if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) {
628 ret = BT_COMPONENT_STATUS_ERROR;
629 goto end;
630 }
631 }
632
633 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
634 switch (encoding) {
635 case BT_CTF_STRING_ENCODING_UTF8:
636 case BT_CTF_STRING_ENCODING_ASCII:
637 g_string_append_c(pretty->tmp_string, (int) v.u);
638 goto end;
639 case BT_CTF_STRING_ENCODING_NONE:
640 case BT_CTF_STRING_ENCODING_UNKNOWN:
641 break;
642 default:
643 ret = BT_COMPONENT_STATUS_ERROR;
644 goto end;
645 }
646
647 if (pretty->use_colors) {
648 g_string_append(pretty->string, COLOR_NUMBER_VALUE);
649 rst_color = true;
650 }
651
652 base = bt_ctf_field_type_integer_get_base(field_type);
653 switch (base) {
654 case BT_CTF_INTEGER_BASE_BINARY:
655 {
656 int bitnr, len;
657
658 len = bt_ctf_field_type_integer_get_size(field_type);
659 if (len < 0) {
660 ret = BT_COMPONENT_STATUS_ERROR;
661 goto end;
662 }
663 g_string_append(pretty->string, "0b");
664 v.u = _bt_piecewise_lshift(v.u, 64 - len);
665 for (bitnr = 0; bitnr < len; bitnr++) {
666 g_string_append_printf(pretty->string, "%u", (v.u & (1ULL << 63)) ? 1 : 0);
667 v.u = _bt_piecewise_lshift(v.u, 1);
668 }
669 break;
670 }
671 case BT_CTF_INTEGER_BASE_OCTAL:
672 {
673 if (signedness) {
674 int len;
675
676 len = bt_ctf_field_type_integer_get_size(field_type);
677 if (len < 0) {
678 ret = BT_COMPONENT_STATUS_ERROR;
679 goto end;
680 }
681 if (len < 64) {
682 size_t rounded_len;
683
684 assert(len != 0);
685 /* Round length to the nearest 3-bit */
686 rounded_len = (((len - 1) / 3) + 1) * 3;
687 v.u &= ((uint64_t) 1 << rounded_len) - 1;
688 }
689 }
690
691 g_string_append_printf(pretty->string, "0%" PRIo64, v.u);
692 break;
693 }
694 case BT_CTF_INTEGER_BASE_DECIMAL:
695 if (!signedness) {
696 g_string_append_printf(pretty->string, "%" PRIu64, v.u);
697 } else {
698 g_string_append_printf(pretty->string, "%" PRId64, v.s);
699 }
700 break;
701 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
702 {
703 int len;
704
705 len = bt_ctf_field_type_integer_get_size(field_type);
706 if (len < 0) {
707 ret = BT_COMPONENT_STATUS_ERROR;
708 goto end;
709 }
710 if (len < 64) {
711 /* Round length to the nearest nibble */
712 uint8_t rounded_len = ((len + 3) & ~0x3);
713
714 v.u &= ((uint64_t) 1 << rounded_len) - 1;
715 }
716
717 g_string_append_printf(pretty->string, "0x%" PRIX64, v.u);
718 break;
719 }
720 default:
721 ret = BT_COMPONENT_STATUS_ERROR;
722 goto end;
723 }
724 end:
725 if (rst_color) {
726 g_string_append(pretty->string, COLOR_RST);
727 }
728 bt_put(field_type);
729 return ret;
730 }
731
732 static
733 void print_escape_string(struct pretty_component *pretty, const char *str)
734 {
735 int i;
736
737 g_string_append_c(pretty->string, '"');
738
739 for (i = 0; i < strlen(str); i++) {
740 /* Escape sequences not recognized by iscntrl(). */
741 switch (str[i]) {
742 case '\\':
743 g_string_append(pretty->string, "\\\\");
744 continue;
745 case '\'':
746 g_string_append(pretty->string, "\\\'");
747 continue;
748 case '\"':
749 g_string_append(pretty->string, "\\\"");
750 continue;
751 case '\?':
752 g_string_append(pretty->string, "\\\?");
753 continue;
754 }
755
756 /* Standard characters. */
757 if (!iscntrl(str[i])) {
758 g_string_append_c(pretty->string, str[i]);
759 continue;
760 }
761
762 switch (str[i]) {
763 case '\0':
764 g_string_append(pretty->string, "\\0");
765 break;
766 case '\a':
767 g_string_append(pretty->string, "\\a");
768 break;
769 case '\b':
770 g_string_append(pretty->string, "\\b");
771 break;
772 case '\e':
773 g_string_append(pretty->string, "\\e");
774 break;
775 case '\f':
776 g_string_append(pretty->string, "\\f");
777 break;
778 case '\n':
779 g_string_append(pretty->string, "\\n");
780 break;
781 case '\r':
782 g_string_append(pretty->string, "\\r");
783 break;
784 case '\t':
785 g_string_append(pretty->string, "\\t");
786 break;
787 case '\v':
788 g_string_append(pretty->string, "\\v");
789 break;
790 default:
791 /* Unhandled control-sequence, print as hex. */
792 g_string_append_printf(pretty->string, "\\x%02x", str[i]);
793 break;
794 }
795 }
796
797 g_string_append_c(pretty->string, '"');
798 }
799
800 static
801 enum bt_component_status print_enum(struct pretty_component *pretty,
802 struct bt_ctf_field *field)
803 {
804 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
805 struct bt_ctf_field *container_field = NULL;
806 struct bt_ctf_field_type *enumeration_field_type = NULL;
807 struct bt_ctf_field_type *container_field_type = NULL;
808 struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL;
809 int nr_mappings = 0;
810 int is_signed;
811
812 enumeration_field_type = bt_ctf_field_get_type(field);
813 if (!enumeration_field_type) {
814 ret = BT_COMPONENT_STATUS_ERROR;
815 goto end;
816 }
817 container_field = bt_ctf_field_enumeration_get_container(field);
818 if (!container_field) {
819 ret = BT_COMPONENT_STATUS_ERROR;
820 goto end;
821 }
822 container_field_type = bt_ctf_field_get_type(container_field);
823 if (!container_field_type) {
824 ret = BT_COMPONENT_STATUS_ERROR;
825 goto end;
826 }
827 is_signed = bt_ctf_field_type_integer_get_signed(container_field_type);
828 if (is_signed < 0) {
829 ret = BT_COMPONENT_STATUS_ERROR;
830 goto end;
831 }
832 if (is_signed) {
833 int64_t value;
834
835 if (bt_ctf_field_signed_integer_get_value(container_field,
836 &value)) {
837 ret = BT_COMPONENT_STATUS_ERROR;
838 goto end;
839 }
840 iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value(
841 enumeration_field_type, value);
842 } else {
843 uint64_t value;
844
845 if (bt_ctf_field_unsigned_integer_get_value(container_field,
846 &value)) {
847 ret = BT_COMPONENT_STATUS_ERROR;
848 goto end;
849 }
850 iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(
851 enumeration_field_type, value);
852 }
853 if (!iter) {
854 ret = BT_COMPONENT_STATUS_ERROR;
855 goto end;
856 }
857 g_string_append(pretty->string, "( ");
858 for (;;) {
859 const char *mapping_name;
860
861 if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
862 iter, &mapping_name, NULL, NULL) < 0) {
863 ret = BT_COMPONENT_STATUS_ERROR;
864 goto end;
865 }
866 if (nr_mappings++)
867 g_string_append(pretty->string, ", ");
868 if (pretty->use_colors) {
869 g_string_append(pretty->string, COLOR_ENUM_MAPPING_NAME);
870 }
871 print_escape_string(pretty, mapping_name);
872 if (pretty->use_colors) {
873 g_string_append(pretty->string, COLOR_RST);
874 }
875 if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) {
876 break;
877 }
878 }
879 if (!nr_mappings) {
880 if (pretty->use_colors) {
881 g_string_append(pretty->string, COLOR_UNKNOWN);
882 }
883 g_string_append(pretty->string, "<unknown>");
884 if (pretty->use_colors) {
885 g_string_append(pretty->string, COLOR_RST);
886 }
887 }
888 g_string_append(pretty->string, " : container = ");
889 ret = print_integer(pretty, container_field);
890 if (ret != BT_COMPONENT_STATUS_OK) {
891 goto end;
892 }
893 g_string_append(pretty->string, " )");
894 end:
895 bt_put(iter);
896 bt_put(container_field_type);
897 bt_put(container_field);
898 bt_put(enumeration_field_type);
899 return ret;
900 }
901
902 static
903 int filter_field_name(struct pretty_component *pretty, const char *field_name,
904 GQuark *filter_fields, int filter_array_len)
905 {
906 int i;
907 GQuark field_quark = g_quark_try_string(field_name);
908
909 if (!field_quark || pretty->options.verbose) {
910 return 1;
911 }
912
913 for (i = 0; i < filter_array_len; i++) {
914 if (field_quark == filter_fields[i]) {
915 return 0;
916 }
917 }
918 return 1;
919 }
920
921 static
922 enum bt_component_status print_struct_field(struct pretty_component *pretty,
923 struct bt_ctf_field *_struct,
924 struct bt_ctf_field_type *struct_type,
925 int i, bool print_names, int *nr_printed_fields,
926 GQuark *filter_fields, int filter_array_len)
927 {
928 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
929 const char *field_name;
930 struct bt_ctf_field *field = NULL;
931 struct bt_ctf_field_type *field_type = NULL;;
932
933 field = bt_ctf_field_structure_get_field_by_index(_struct, i);
934 if (!field) {
935 ret = BT_COMPONENT_STATUS_ERROR;
936 goto end;
937 }
938 if (bt_ctf_field_type_structure_get_field(struct_type,
939 &field_name, &field_type, i) < 0) {
940 ret = BT_COMPONENT_STATUS_ERROR;
941 goto end;
942 }
943
944 if (filter_fields && !filter_field_name(pretty, field_name,
945 filter_fields, filter_array_len)) {
946 ret = BT_COMPONENT_STATUS_OK;
947 goto end;
948 }
949
950 if (*nr_printed_fields > 0) {
951 g_string_append(pretty->string, ", ");
952 } else {
953 g_string_append(pretty->string, " ");
954 }
955 if (print_names) {
956 print_field_name_equal(pretty, rem_(field_name));
957 }
958 ret = print_field(pretty, field, print_names, NULL, 0);
959 *nr_printed_fields += 1;
960 end:
961 bt_put(field_type);
962 bt_put(field);
963 return ret;
964 }
965
966 static
967 enum bt_component_status print_struct(struct pretty_component *pretty,
968 struct bt_ctf_field *_struct, bool print_names,
969 GQuark *filter_fields, int filter_array_len)
970 {
971 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
972 struct bt_ctf_field_type *struct_type = NULL;
973 int nr_fields, i, nr_printed_fields;
974
975 struct_type = bt_ctf_field_get_type(_struct);
976 if (!struct_type) {
977 ret = BT_COMPONENT_STATUS_ERROR;
978 goto end;
979 }
980 nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type);
981 if (nr_fields < 0) {
982 ret = BT_COMPONENT_STATUS_ERROR;
983 goto end;
984 }
985 g_string_append(pretty->string, "{");
986 pretty->depth++;
987 nr_printed_fields = 0;
988 for (i = 0; i < nr_fields; i++) {
989 ret = print_struct_field(pretty, _struct, struct_type, i,
990 print_names, &nr_printed_fields, filter_fields,
991 filter_array_len);
992 if (ret != BT_COMPONENT_STATUS_OK) {
993 goto end;
994 }
995 }
996 pretty->depth--;
997 g_string_append(pretty->string, " }");
998 end:
999 bt_put(struct_type);
1000 return ret;
1001 }
1002
1003 static
1004 enum bt_component_status print_array_field(struct pretty_component *pretty,
1005 struct bt_ctf_field *array, uint64_t i,
1006 bool is_string, bool print_names)
1007 {
1008 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1009 struct bt_ctf_field *field = NULL;
1010
1011 if (!is_string) {
1012 if (i != 0) {
1013 g_string_append(pretty->string, ", ");
1014 } else {
1015 g_string_append(pretty->string, " ");
1016 }
1017 if (print_names) {
1018 g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
1019 }
1020 }
1021 field = bt_ctf_field_array_get_field(array, i);
1022 if (!field) {
1023 ret = BT_COMPONENT_STATUS_ERROR;
1024 goto end;
1025 }
1026 ret = print_field(pretty, field, print_names, NULL, 0);
1027 end:
1028 bt_put(field);
1029 return ret;
1030 }
1031
1032 static
1033 enum bt_component_status print_array(struct pretty_component *pretty,
1034 struct bt_ctf_field *array, bool print_names)
1035 {
1036 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1037 struct bt_ctf_field_type *array_type = NULL, *field_type = NULL;
1038 enum bt_ctf_field_type_id type_id;
1039 int64_t len;
1040 uint64_t i;
1041 bool is_string = false;
1042
1043 array_type = bt_ctf_field_get_type(array);
1044 if (!array_type) {
1045 ret = BT_COMPONENT_STATUS_ERROR;
1046 goto end;
1047 }
1048 field_type = bt_ctf_field_type_array_get_element_type(array_type);
1049 if (!field_type) {
1050 ret = BT_COMPONENT_STATUS_ERROR;
1051 goto end;
1052 }
1053 len = bt_ctf_field_type_array_get_length(array_type);
1054 if (len < 0) {
1055 ret = BT_COMPONENT_STATUS_ERROR;
1056 goto end;
1057 }
1058 type_id = bt_ctf_field_type_get_type_id(field_type);
1059 if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) {
1060 enum bt_ctf_string_encoding encoding;
1061
1062 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
1063 if (encoding == BT_CTF_STRING_ENCODING_UTF8
1064 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
1065 int integer_len, integer_alignment;
1066
1067 integer_len = bt_ctf_field_type_integer_get_size(field_type);
1068 if (integer_len < 0) {
1069 return BT_COMPONENT_STATUS_ERROR;
1070 }
1071 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
1072 if (integer_alignment < 0) {
1073 return BT_COMPONENT_STATUS_ERROR;
1074 }
1075 if (integer_len == CHAR_BIT
1076 && integer_alignment == CHAR_BIT) {
1077 is_string = true;
1078 }
1079 }
1080 }
1081
1082 if (is_string) {
1083 g_string_assign(pretty->tmp_string, "");
1084 } else {
1085 g_string_append(pretty->string, "[");
1086 }
1087
1088 pretty->depth++;
1089 for (i = 0; i < len; i++) {
1090 ret = print_array_field(pretty, array, i, is_string, print_names);
1091 if (ret != BT_COMPONENT_STATUS_OK) {
1092 goto end;
1093 }
1094 }
1095 pretty->depth--;
1096
1097 if (is_string) {
1098 if (pretty->use_colors) {
1099 g_string_append(pretty->string, COLOR_STRING_VALUE);
1100 }
1101 print_escape_string(pretty, pretty->tmp_string->str);
1102 if (pretty->use_colors) {
1103 g_string_append(pretty->string, COLOR_RST);
1104 }
1105 } else {
1106 g_string_append(pretty->string, " ]");
1107 }
1108 end:
1109 bt_put(field_type);
1110 bt_put(array_type);
1111 return ret;
1112 }
1113
1114 static
1115 enum bt_component_status print_sequence_field(struct pretty_component *pretty,
1116 struct bt_ctf_field *seq, uint64_t i,
1117 bool is_string, bool print_names)
1118 {
1119 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1120 struct bt_ctf_field *field = NULL;
1121
1122 if (!is_string) {
1123 if (i != 0) {
1124 g_string_append(pretty->string, ", ");
1125 } else {
1126 g_string_append(pretty->string, " ");
1127 }
1128 if (print_names) {
1129 g_string_append_printf(pretty->string, "[%" PRIu64 "] = ", i);
1130 }
1131 }
1132 field = bt_ctf_field_sequence_get_field(seq, i);
1133 if (!field) {
1134 ret = BT_COMPONENT_STATUS_ERROR;
1135 goto end;
1136 }
1137 ret = print_field(pretty, field, print_names, NULL, 0);
1138 end:
1139 bt_put(field);
1140 return ret;
1141 }
1142
1143 static
1144 enum bt_component_status print_sequence(struct pretty_component *pretty,
1145 struct bt_ctf_field *seq, bool print_names)
1146 {
1147 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1148 struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL;
1149 struct bt_ctf_field *length_field = NULL;
1150 enum bt_ctf_field_type_id type_id;
1151 uint64_t len;
1152 uint64_t i;
1153 bool is_string = false;
1154
1155 seq_type = bt_ctf_field_get_type(seq);
1156 if (!seq_type) {
1157 ret = BT_COMPONENT_STATUS_ERROR;
1158 goto end;
1159 }
1160 length_field = bt_ctf_field_sequence_get_length(seq);
1161 if (!length_field) {
1162 ret = BT_COMPONENT_STATUS_ERROR;
1163 goto end;
1164 }
1165 if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) {
1166 ret = BT_COMPONENT_STATUS_ERROR;
1167 goto end;
1168 }
1169 field_type = bt_ctf_field_type_sequence_get_element_type(seq_type);
1170 if (!field_type) {
1171 ret = BT_COMPONENT_STATUS_ERROR;
1172 goto end;
1173 }
1174 type_id = bt_ctf_field_type_get_type_id(field_type);
1175 if (type_id == BT_CTF_FIELD_TYPE_ID_INTEGER) {
1176 enum bt_ctf_string_encoding encoding;
1177
1178 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
1179 if (encoding == BT_CTF_STRING_ENCODING_UTF8
1180 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
1181 int integer_len, integer_alignment;
1182
1183 integer_len = bt_ctf_field_type_integer_get_size(field_type);
1184 if (integer_len < 0) {
1185 ret = BT_COMPONENT_STATUS_ERROR;
1186 goto end;
1187 }
1188 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
1189 if (integer_alignment < 0) {
1190 ret = BT_COMPONENT_STATUS_ERROR;
1191 goto end;
1192 }
1193 if (integer_len == CHAR_BIT
1194 && integer_alignment == CHAR_BIT) {
1195 is_string = true;
1196 }
1197 }
1198 }
1199
1200 if (is_string) {
1201 g_string_assign(pretty->tmp_string, "");
1202 } else {
1203 g_string_append(pretty->string, "[");
1204 }
1205
1206 pretty->depth++;
1207 for (i = 0; i < len; i++) {
1208 ret = print_sequence_field(pretty, seq, i,
1209 is_string, print_names);
1210 if (ret != BT_COMPONENT_STATUS_OK) {
1211 goto end;
1212 }
1213 }
1214 pretty->depth--;
1215
1216 if (is_string) {
1217 if (pretty->use_colors) {
1218 g_string_append(pretty->string, COLOR_STRING_VALUE);
1219 }
1220 print_escape_string(pretty, pretty->tmp_string->str);
1221 if (pretty->use_colors) {
1222 g_string_append(pretty->string, COLOR_RST);
1223 }
1224 } else {
1225 g_string_append(pretty->string, " ]");
1226 }
1227 end:
1228 bt_put(length_field);
1229 bt_put(field_type);
1230 bt_put(seq_type);
1231 return ret;
1232 }
1233
1234 static
1235 enum bt_component_status print_variant(struct pretty_component *pretty,
1236 struct bt_ctf_field *variant, bool print_names)
1237 {
1238 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1239 struct bt_ctf_field *field = NULL;
1240
1241 field = bt_ctf_field_variant_get_current_field(variant);
1242 if (!field) {
1243 ret = BT_COMPONENT_STATUS_ERROR;
1244 goto end;
1245 }
1246 g_string_append(pretty->string, "{ ");
1247 pretty->depth++;
1248 if (print_names) {
1249 int iter_ret;
1250 struct bt_ctf_field *tag_field = NULL;
1251 const char *tag_choice;
1252 struct bt_ctf_field_type_enumeration_mapping_iterator *iter;
1253
1254 tag_field = bt_ctf_field_variant_get_tag(variant);
1255 if (!tag_field) {
1256 ret = BT_COMPONENT_STATUS_ERROR;
1257 goto end;
1258 }
1259
1260 iter = bt_ctf_field_enumeration_get_mappings(tag_field);
1261 if (!iter) {
1262 bt_put(tag_field);
1263 ret = BT_COMPONENT_STATUS_ERROR;
1264 goto end;
1265 }
1266
1267 iter_ret =
1268 bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
1269 iter, &tag_choice, NULL, NULL);
1270 if (iter_ret) {
1271 bt_put(iter);
1272 bt_put(tag_field);
1273 ret = BT_COMPONENT_STATUS_ERROR;
1274 goto end;
1275 }
1276 print_field_name_equal(pretty, rem_(tag_choice));
1277 bt_put(tag_field);
1278 bt_put(iter);
1279 }
1280 ret = print_field(pretty, field, print_names, NULL, 0);
1281 if (ret != BT_COMPONENT_STATUS_OK) {
1282 goto end;
1283 }
1284 pretty->depth--;
1285 g_string_append(pretty->string, " }");
1286 end:
1287 bt_put(field);
1288 return ret;
1289 }
1290
1291 static
1292 enum bt_component_status print_field(struct pretty_component *pretty,
1293 struct bt_ctf_field *field, bool print_names,
1294 GQuark *filter_fields, int filter_array_len)
1295 {
1296 enum bt_ctf_field_type_id type_id;
1297
1298 type_id = bt_ctf_field_get_type_id(field);
1299 switch (type_id) {
1300 case CTF_TYPE_INTEGER:
1301 return print_integer(pretty, field);
1302 case CTF_TYPE_FLOAT:
1303 {
1304 double v;
1305
1306 if (bt_ctf_field_floating_point_get_value(field, &v)) {
1307 return BT_COMPONENT_STATUS_ERROR;
1308 }
1309 if (pretty->use_colors) {
1310 g_string_append(pretty->string, COLOR_NUMBER_VALUE);
1311 }
1312 g_string_append_printf(pretty->string, "%g", v);
1313 if (pretty->use_colors) {
1314 g_string_append(pretty->string, COLOR_RST);
1315 }
1316 return BT_COMPONENT_STATUS_OK;
1317 }
1318 case CTF_TYPE_ENUM:
1319 return print_enum(pretty, field);
1320 case CTF_TYPE_STRING:
1321 if (pretty->use_colors) {
1322 g_string_append(pretty->string, COLOR_STRING_VALUE);
1323 }
1324 print_escape_string(pretty, bt_ctf_field_string_get_value(field));
1325 if (pretty->use_colors) {
1326 g_string_append(pretty->string, COLOR_RST);
1327 }
1328 return BT_COMPONENT_STATUS_OK;
1329 case CTF_TYPE_STRUCT:
1330 return print_struct(pretty, field, print_names, filter_fields,
1331 filter_array_len);
1332 case CTF_TYPE_VARIANT:
1333 return print_variant(pretty, field, print_names);
1334 case CTF_TYPE_ARRAY:
1335 return print_array(pretty, field, print_names);
1336 case CTF_TYPE_SEQUENCE:
1337 return print_sequence(pretty, field, print_names);
1338 default:
1339 // TODO: log instead
1340 fprintf(pretty->err, "[error] Unknown type id: %d\n", (int) type_id);
1341 return BT_COMPONENT_STATUS_ERROR;
1342 }
1343 }
1344
1345 static
1346 enum bt_component_status print_stream_packet_context(struct pretty_component *pretty,
1347 struct bt_ctf_event *event)
1348 {
1349 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1350 struct bt_ctf_packet *packet = NULL;
1351 struct bt_ctf_field *main_field = NULL;
1352
1353 packet = bt_ctf_event_get_packet(event);
1354 if (!packet) {
1355 ret = BT_COMPONENT_STATUS_ERROR;
1356 goto end;
1357 }
1358 main_field = bt_ctf_packet_get_context(packet);
1359 if (!main_field) {
1360 goto end;
1361 }
1362 if (!pretty->start_line) {
1363 g_string_append(pretty->string, ", ");
1364 }
1365 pretty->start_line = false;
1366 if (pretty->options.print_scope_field_names) {
1367 print_name_equal(pretty, "stream.packet.context");
1368 }
1369 ret = print_field(pretty, main_field,
1370 pretty->options.print_context_field_names,
1371 stream_packet_context_quarks,
1372 STREAM_PACKET_CONTEXT_QUARKS_LEN);
1373 end:
1374 bt_put(main_field);
1375 bt_put(packet);
1376 return ret;
1377 }
1378
1379 static
1380 enum bt_component_status print_event_header_raw(struct pretty_component *pretty,
1381 struct bt_ctf_event *event)
1382 {
1383 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1384 struct bt_ctf_field *main_field = NULL;
1385
1386 main_field = bt_ctf_event_get_header(event);
1387 if (!main_field) {
1388 goto end;
1389 }
1390 if (!pretty->start_line) {
1391 g_string_append(pretty->string, ", ");
1392 }
1393 pretty->start_line = false;
1394 if (pretty->options.print_scope_field_names) {
1395 print_name_equal(pretty, "stream.event.header");
1396 }
1397 ret = print_field(pretty, main_field,
1398 pretty->options.print_header_field_names, NULL, 0);
1399 end:
1400 bt_put(main_field);
1401 return ret;
1402 }
1403
1404 static
1405 enum bt_component_status print_stream_event_context(struct pretty_component *pretty,
1406 struct bt_ctf_event *event)
1407 {
1408 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1409 struct bt_ctf_field *main_field = NULL;
1410
1411 main_field = bt_ctf_event_get_stream_event_context(event);
1412 if (!main_field) {
1413 goto end;
1414 }
1415 if (!pretty->start_line) {
1416 g_string_append(pretty->string, ", ");
1417 }
1418 pretty->start_line = false;
1419 if (pretty->options.print_scope_field_names) {
1420 print_name_equal(pretty, "stream.event.context");
1421 }
1422 ret = print_field(pretty, main_field,
1423 pretty->options.print_context_field_names, NULL, 0);
1424 end:
1425 bt_put(main_field);
1426 return ret;
1427 }
1428
1429 static
1430 enum bt_component_status print_event_context(struct pretty_component *pretty,
1431 struct bt_ctf_event *event)
1432 {
1433 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1434 struct bt_ctf_field *main_field = NULL;
1435
1436 main_field = bt_ctf_event_get_event_context(event);
1437 if (!main_field) {
1438 goto end;
1439 }
1440 if (!pretty->start_line) {
1441 g_string_append(pretty->string, ", ");
1442 }
1443 pretty->start_line = false;
1444 if (pretty->options.print_scope_field_names) {
1445 print_name_equal(pretty, "event.context");
1446 }
1447 ret = print_field(pretty, main_field,
1448 pretty->options.print_context_field_names, NULL, 0);
1449 end:
1450 bt_put(main_field);
1451 return ret;
1452 }
1453
1454 static
1455 enum bt_component_status print_event_payload(struct pretty_component *pretty,
1456 struct bt_ctf_event *event)
1457 {
1458 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1459 struct bt_ctf_field *main_field = NULL;
1460
1461 main_field = bt_ctf_event_get_event_payload(event);
1462 if (!main_field) {
1463 goto end;
1464 }
1465 if (!pretty->start_line) {
1466 g_string_append(pretty->string, ", ");
1467 }
1468 pretty->start_line = false;
1469 if (pretty->options.print_scope_field_names) {
1470 print_name_equal(pretty, "event.fields");
1471 }
1472 ret = print_field(pretty, main_field,
1473 pretty->options.print_payload_field_names, NULL, 0);
1474 end:
1475 bt_put(main_field);
1476 return ret;
1477 }
1478
1479 BT_HIDDEN
1480 enum bt_component_status pretty_print_event(struct pretty_component *pretty,
1481 struct bt_notification *event_notif)
1482 {
1483 enum bt_component_status ret;
1484 struct bt_ctf_event *event =
1485 bt_notification_event_get_event(event_notif);
1486 struct bt_clock_class_priority_map *cc_prio_map =
1487 bt_notification_event_get_clock_class_priority_map(event_notif);
1488
1489 assert(event);
1490 assert(cc_prio_map);
1491 pretty->start_line = true;
1492 g_string_assign(pretty->string, "");
1493 ret = print_event_header(pretty, event, cc_prio_map);
1494 if (ret != BT_COMPONENT_STATUS_OK) {
1495 goto end;
1496 }
1497
1498 ret = print_stream_packet_context(pretty, event);
1499 if (ret != BT_COMPONENT_STATUS_OK) {
1500 goto end;
1501 }
1502
1503 if (pretty->options.verbose) {
1504 ret = print_event_header_raw(pretty, event);
1505 if (ret != BT_COMPONENT_STATUS_OK) {
1506 goto end;
1507 }
1508 }
1509
1510 ret = print_stream_event_context(pretty, event);
1511 if (ret != BT_COMPONENT_STATUS_OK) {
1512 goto end;
1513 }
1514
1515 ret = print_event_context(pretty, event);
1516 if (ret != BT_COMPONENT_STATUS_OK) {
1517 goto end;
1518 }
1519
1520 ret = print_event_payload(pretty, event);
1521 if (ret != BT_COMPONENT_STATUS_OK) {
1522 goto end;
1523 }
1524
1525 g_string_append_c(pretty->string, '\n');
1526 if (fwrite(pretty->string->str, pretty->string->len, 1, pretty->out) != 1) {
1527 ret = BT_COMPONENT_STATUS_ERROR;
1528 goto end;
1529 }
1530
1531 end:
1532 bt_put(event);
1533 bt_put(cc_prio_map);
1534 return ret;
1535 }
This page took 0.070897 seconds and 5 git commands to generate.