4 * Babeltrace CTF Text Output Plugin Event Printing
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
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:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
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
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/bitfield.h>
40 #include <babeltrace/common-internal.h>
44 #define NSEC_PER_SEC 1000000000LL
46 #define COLOR_NAME BT_COMMON_COLOR_BOLD
47 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
48 #define COLOR_RST BT_COMMON_COLOR_RESET
49 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_GREEN
50 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
51 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_CYAN
52 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
53 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
54 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
57 const char *rem_(const char *str
)
66 int64_t real_timestamp
; /* Relative to UNIX epoch. */
67 uint64_t clock_value
; /* In cycles. */
71 enum bt_component_status
print_field(struct text_component
*text
,
72 struct bt_ctf_field
*field
, bool print_names
);
75 void print_name_equal(struct text_component
*text
, const char *name
)
77 if (text
->use_colors
) {
78 fprintf(text
->out
, "%s%s%s = ", COLOR_NAME
, name
, COLOR_RST
);
80 fputs(name
, text
->out
);
85 void print_field_name_equal(struct text_component
*text
, const char *name
)
87 if (text
->use_colors
) {
88 fprintf(text
->out
, "%s%s%s = ", COLOR_FIELD_NAME
, name
,
91 fputs(name
, text
->out
);
96 void print_timestamp_cycles(struct text_component
*text
,
97 struct bt_ctf_clock_class
*clock_class
,
98 struct bt_ctf_event
*event
)
101 struct bt_ctf_clock_value
*clock_value
;
104 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
106 fputs("????????????????????", text
->out
);
110 ret
= bt_ctf_clock_value_get_value(clock_value
, &cycles
);
113 fprintf(text
->out
, "Error");
116 fprintf(text
->out
, "%020" PRIu64
, cycles
);
118 if (text
->last_cycles_timestamp
!= -1ULL) {
119 text
->delta_cycles
= cycles
- text
->last_cycles_timestamp
;
121 text
->last_cycles_timestamp
= cycles
;
125 void print_timestamp_wall(struct text_component
*text
,
126 struct bt_ctf_clock_class
*clock_class
,
127 struct bt_ctf_event
*event
)
130 struct bt_ctf_clock_value
*clock_value
;
131 int64_t ts_nsec
= 0; /* add configurable offset */
132 int64_t ts_sec
= 0; /* add configurable offset */
133 uint64_t ts_sec_abs
, ts_nsec_abs
;
136 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
138 fputs("??:??:??.?????????", text
->out
);
142 ret
= bt_ctf_clock_value_get_value_ns_from_epoch(clock_value
, &ts_nsec
);
145 fprintf(text
->out
, "Error");
149 if (text
->last_real_timestamp
!= -1ULL) {
150 text
->delta_real_timestamp
= ts_nsec
- text
->last_real_timestamp
;
152 text
->last_real_timestamp
= ts_nsec
;
154 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
155 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
156 if (ts_sec
>= 0 && ts_nsec
>= 0) {
159 ts_nsec_abs
= ts_nsec
;
160 } else if (ts_sec
> 0 && ts_nsec
< 0) {
162 ts_sec_abs
= ts_sec
- 1;
163 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
164 } else if (ts_sec
== 0 && ts_nsec
< 0) {
167 ts_nsec_abs
= -ts_nsec
;
168 } else if (ts_sec
< 0 && ts_nsec
> 0) {
170 ts_sec_abs
= -(ts_sec
+ 1);
171 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
172 } else if (ts_sec
< 0 && ts_nsec
== 0) {
174 ts_sec_abs
= -ts_sec
;
175 ts_nsec_abs
= ts_nsec
;
176 } else { /* (ts_sec < 0 && ts_nsec < 0) */
178 ts_sec_abs
= -ts_sec
;
179 ts_nsec_abs
= -ts_nsec
;
182 if (!text
->options
.clock_seconds
) {
184 time_t time_s
= (time_t) ts_sec_abs
;
187 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
191 if (!text
->options
.clock_gmt
) {
194 res
= localtime_r(&time_s
, &tm
);
196 fprintf(stderr
, "[warning] Unable to get localtime.\n");
202 res
= gmtime_r(&time_s
, &tm
);
204 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
208 if (text
->options
.clock_date
) {
212 /* Print date and time */
213 res
= strftime(timestr
, sizeof(timestr
),
216 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
219 fprintf(text
->out
, "%s", timestr
);
221 /* Print time in HH:MM:SS.ns */
222 fprintf(text
->out
, "%02d:%02d:%02d.%09" PRIu64
,
223 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
, ts_nsec_abs
);
227 fprintf(text
->out
, "%s%" PRId64
".%09" PRIu64
,
228 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
234 enum bt_component_status
print_event_timestamp(struct text_component
*text
,
235 struct bt_ctf_event
*event
, bool *start_line
)
237 bool print_names
= text
->options
.print_header_field_names
;
238 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
239 struct bt_ctf_stream
*stream
= NULL
;
240 struct bt_ctf_stream_class
*stream_class
= NULL
;
241 struct bt_ctf_trace
*trace
= NULL
;
242 struct bt_ctf_clock_class
*clock_class
= NULL
;
243 FILE *out
= text
->out
;
245 stream
= bt_ctf_event_get_stream(event
);
247 ret
= BT_COMPONENT_STATUS_ERROR
;
251 stream_class
= bt_ctf_stream_get_class(stream
);
253 ret
= BT_COMPONENT_STATUS_ERROR
;
256 trace
= bt_ctf_stream_class_get_trace(stream_class
);
258 ret
= BT_COMPONENT_STATUS_ERROR
;
261 clock_class
= bt_ctf_trace_get_clock_class(trace
, 0);
263 ret
= BT_COMPONENT_STATUS_ERROR
;
268 print_name_equal(text
, "timestamp");
272 if (text
->use_colors
) {
273 fputs(COLOR_TIMESTAMP
, text
->out
);
275 if (text
->options
.print_timestamp_cycles
) {
276 print_timestamp_cycles(text
, clock_class
, event
);
278 print_timestamp_wall(text
, clock_class
, event
);
280 if (text
->use_colors
) {
281 fputs(COLOR_RST
, text
->out
);
287 if (text
->options
.print_delta_field
) {
289 fputs(", ", text
->out
);
290 print_name_equal(text
, "delta");
292 fputs("(", text
->out
);
294 if (text
->options
.print_timestamp_cycles
) {
295 if (text
->delta_cycles
== -1ULL) {
296 fputs("+??????????\?\?) ", text
->out
); /* Not a trigraph. */
298 fprintf(text
->out
, "+%012" PRIu64
, text
->delta_cycles
);
301 if (text
->delta_real_timestamp
!= -1ULL) {
302 uint64_t delta_sec
, delta_nsec
, delta
;
304 delta
= text
->delta_real_timestamp
;
305 delta_sec
= delta
/ NSEC_PER_SEC
;
306 delta_nsec
= delta
% NSEC_PER_SEC
;
307 fprintf(text
->out
, "+%" PRIu64
".%09" PRIu64
,
308 delta_sec
, delta_nsec
);
310 fputs("+?.?????????", text
->out
);
314 fputs(") ", text
->out
);
317 *start_line
= !print_names
;
322 bt_put(stream_class
);
328 enum bt_component_status
print_event_header(struct text_component
*text
,
329 struct bt_ctf_event
*event
)
331 bool print_names
= text
->options
.print_header_field_names
;
332 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
333 struct bt_ctf_event_class
*event_class
= NULL
;
334 struct bt_ctf_stream_class
*stream_class
= NULL
;
335 struct bt_ctf_trace
*trace_class
= NULL
;
337 event_class
= bt_ctf_event_get_class(event
);
339 ret
= BT_COMPONENT_STATUS_ERROR
;
342 stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
344 ret
= BT_COMPONENT_STATUS_ERROR
;
347 trace_class
= bt_ctf_stream_class_get_trace(stream_class
);
349 ret
= BT_COMPONENT_STATUS_ERROR
;
352 if (!text
->start_line
) {
353 fputs(", ", text
->out
);
355 text
->start_line
= false;
356 ret
= print_event_timestamp(text
, event
, &text
->start_line
);
357 if (ret
!= BT_COMPONENT_STATUS_OK
) {
360 if (text
->options
.print_trace_field
) {
363 name
= bt_ctf_trace_get_name(trace_class
);
365 if (!text
->start_line
) {
366 fputs(", ", text
->out
);
368 text
->start_line
= false;
370 print_name_equal(text
, "trace");
372 fprintf(text
->out
, "%s", name
);
375 if (text
->options
.print_trace_hostname_field
) {
376 struct bt_value
*hostname_str
;
378 hostname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
383 if (!text
->start_line
) {
384 fputs(", ", text
->out
);
386 text
->start_line
= false;
388 print_name_equal(text
, "trace:hostname");
390 if (bt_value_string_get(hostname_str
, &str
)
391 == BT_VALUE_STATUS_OK
) {
392 fprintf(text
->out
, "%s", str
);
394 bt_put(hostname_str
);
397 if (text
->options
.print_trace_domain_field
) {
398 struct bt_value
*domain_str
;
400 domain_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
405 if (!text
->start_line
) {
406 fputs(", ", text
->out
);
408 text
->start_line
= false;
410 print_name_equal(text
, "trace:domain");
412 if (bt_value_string_get(domain_str
, &str
)
413 == BT_VALUE_STATUS_OK
) {
414 fprintf(text
->out
, "%s", str
);
419 if (text
->options
.print_trace_procname_field
) {
420 struct bt_value
*procname_str
;
422 procname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
427 if (!text
->start_line
) {
428 fputs(", ", text
->out
);
430 text
->start_line
= false;
432 print_name_equal(text
, "trace:procname");
434 if (bt_value_string_get(procname_str
, &str
)
435 == BT_VALUE_STATUS_OK
) {
436 fprintf(text
->out
, "%s", str
);
438 bt_put(procname_str
);
441 if (text
->options
.print_trace_vpid_field
) {
442 struct bt_value
*vpid_value
;
444 vpid_value
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
449 if (!text
->start_line
) {
450 fputs(", ", text
->out
);
452 text
->start_line
= false;
454 print_name_equal(text
, "trace:vpid");
456 if (bt_value_integer_get(vpid_value
, &value
)
457 == BT_VALUE_STATUS_OK
) {
458 fprintf(text
->out
, "(%" PRId64
")", value
);
463 if (text
->options
.print_loglevel_field
) {
464 struct bt_value
*loglevel_str
, *loglevel_value
;
466 loglevel_str
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
468 loglevel_value
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
470 if (loglevel_str
|| loglevel_value
) {
471 bool has_str
= false;
473 if (!text
->start_line
) {
474 fputs(", ", text
->out
);
476 text
->start_line
= false;
478 print_name_equal(text
, "loglevel");
483 if (bt_value_string_get(loglevel_str
, &str
)
484 == BT_VALUE_STATUS_OK
) {
485 fprintf(text
->out
, "%s", str
);
489 if (loglevel_value
) {
492 if (bt_value_integer_get(loglevel_value
, &value
)
493 == BT_VALUE_STATUS_OK
) {
494 fprintf(text
->out
, "%s(%" PRId64
")",
495 has_str
? " " : "", value
);
498 bt_put(loglevel_str
);
499 bt_put(loglevel_value
);
502 if (text
->options
.print_emf_field
) {
503 struct bt_value
*uri_str
;
505 uri_str
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
508 if (!text
->start_line
) {
509 fputs(", ", text
->out
);
511 text
->start_line
= false;
513 print_name_equal(text
, "model.emf.uri");
518 if (bt_value_string_get(uri_str
, &str
)
519 == BT_VALUE_STATUS_OK
) {
520 fprintf(text
->out
, "%s", str
);
526 if (!text
->start_line
) {
527 fputs(", ", text
->out
);
529 text
->start_line
= false;
531 print_name_equal(text
, "name");
533 if (text
->use_colors
) {
534 fputs(COLOR_EVENT_NAME
, text
->out
);
536 fputs(bt_ctf_event_class_get_name(event_class
), text
->out
);
537 if (text
->use_colors
) {
538 fputs(COLOR_RST
, text
->out
);
542 bt_put(stream_class
);
548 enum bt_component_status
print_integer(struct text_component
*text
,
549 struct bt_ctf_field
*field
)
551 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
552 struct bt_ctf_field_type
*field_type
= NULL
;
553 enum bt_ctf_integer_base base
;
554 enum bt_ctf_string_encoding encoding
;
560 bool rst_color
= false;
562 field_type
= bt_ctf_field_get_type(field
);
564 ret
= BT_COMPONENT_STATUS_ERROR
;
567 signedness
= bt_ctf_field_type_integer_get_signed(field_type
);
568 if (signedness
< 0) {
569 ret
= BT_COMPONENT_STATUS_ERROR
;
573 if (bt_ctf_field_unsigned_integer_get_value(field
, &v
.u
) < 0) {
574 ret
= BT_COMPONENT_STATUS_ERROR
;
578 if (bt_ctf_field_signed_integer_get_value(field
, &v
.s
) < 0) {
579 ret
= BT_COMPONENT_STATUS_ERROR
;
584 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
586 case BT_CTF_STRING_ENCODING_UTF8
:
587 case BT_CTF_STRING_ENCODING_ASCII
:
588 g_string_append_c(text
->string
, (int) v
.u
);
590 case BT_CTF_STRING_ENCODING_NONE
:
591 case BT_CTF_STRING_ENCODING_UNKNOWN
:
594 ret
= BT_COMPONENT_STATUS_ERROR
;
598 if (text
->use_colors
) {
599 fputs(COLOR_NUMBER_VALUE
, text
->out
);
603 base
= bt_ctf_field_type_integer_get_base(field_type
);
605 case BT_CTF_INTEGER_BASE_BINARY
:
609 len
= bt_ctf_field_type_integer_get_size(field_type
);
611 ret
= BT_COMPONENT_STATUS_ERROR
;
614 fprintf(text
->out
, "0b");
615 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
616 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
617 fprintf(text
->out
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
618 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
622 case BT_CTF_INTEGER_BASE_OCTAL
:
627 len
= bt_ctf_field_type_integer_get_size(field_type
);
629 ret
= BT_COMPONENT_STATUS_ERROR
;
636 /* Round length to the nearest 3-bit */
637 rounded_len
= (((len
- 1) / 3) + 1) * 3;
638 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
642 fprintf(text
->out
, "0%" PRIo64
, v
.u
);
645 case BT_CTF_INTEGER_BASE_DECIMAL
:
647 fprintf(text
->out
, "%" PRIu64
, v
.u
);
649 fprintf(text
->out
, "%" PRId64
, v
.s
);
652 case BT_CTF_INTEGER_BASE_HEXADECIMAL
:
656 len
= bt_ctf_field_type_integer_get_size(field_type
);
658 ret
= BT_COMPONENT_STATUS_ERROR
;
662 /* Round length to the nearest nibble */
663 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
665 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
668 fprintf(text
->out
, "0x%" PRIX64
, v
.u
);
672 ret
= BT_COMPONENT_STATUS_ERROR
;
677 fputs(COLOR_RST
, text
->out
);
684 enum bt_component_status
print_enum(struct text_component
*text
,
685 struct bt_ctf_field
*field
)
687 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
688 struct bt_ctf_field
*container_field
= NULL
;
689 struct bt_ctf_field_type
*enumeration_field_type
= NULL
;
690 struct bt_ctf_field_type
*container_field_type
= NULL
;
691 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
= NULL
;
695 enumeration_field_type
= bt_ctf_field_get_type(field
);
696 if (!enumeration_field_type
) {
697 ret
= BT_COMPONENT_STATUS_ERROR
;
700 container_field
= bt_ctf_field_enumeration_get_container(field
);
701 if (!container_field
) {
702 ret
= BT_COMPONENT_STATUS_ERROR
;
705 container_field_type
= bt_ctf_field_get_type(container_field
);
706 if (!container_field_type
) {
707 ret
= BT_COMPONENT_STATUS_ERROR
;
710 is_signed
= bt_ctf_field_type_integer_get_signed(container_field_type
);
712 ret
= BT_COMPONENT_STATUS_ERROR
;
718 if (bt_ctf_field_signed_integer_get_value(container_field
,
720 ret
= BT_COMPONENT_STATUS_ERROR
;
723 iter
= bt_ctf_field_type_enumeration_find_mappings_by_signed_value(
724 enumeration_field_type
, value
);
728 if (bt_ctf_field_unsigned_integer_get_value(container_field
,
730 ret
= BT_COMPONENT_STATUS_ERROR
;
733 iter
= bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(
734 enumeration_field_type
, value
);
737 ret
= BT_COMPONENT_STATUS_ERROR
;
740 fprintf(text
->out
, "( ");
742 const char *mapping_name
;
744 if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
745 iter
, &mapping_name
, NULL
, NULL
) < 0) {
746 ret
= BT_COMPONENT_STATUS_ERROR
;
750 fprintf(text
->out
, ", ");
751 if (text
->use_colors
) {
752 fputs(COLOR_ENUM_MAPPING_NAME
, text
->out
);
754 // TODO: escape string
755 fprintf(text
->out
, "\"%s\"", mapping_name
);
756 if (text
->use_colors
) {
757 fputs(COLOR_RST
, text
->out
);
759 if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter
) < 0) {
764 if (text
->use_colors
) {
765 fputs(COLOR_UNKNOWN
, text
->out
);
767 fprintf(text
->out
, "<unknown>");
768 if (text
->use_colors
) {
769 fputs(COLOR_RST
, text
->out
);
772 fprintf(text
->out
, " : container = ");
773 ret
= print_integer(text
, container_field
);
774 if (ret
!= BT_COMPONENT_STATUS_OK
) {
777 fprintf(text
->out
, " )");
780 bt_put(container_field_type
);
781 bt_put(container_field
);
782 bt_put(enumeration_field_type
);
787 enum bt_component_status
print_struct_field(struct text_component
*text
,
788 struct bt_ctf_field
*_struct
,
789 struct bt_ctf_field_type
*struct_type
,
790 int i
, bool print_names
)
792 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
793 const char *field_name
;
794 struct bt_ctf_field
*field
= NULL
;
795 struct bt_ctf_field_type
*field_type
= NULL
;;
797 field
= bt_ctf_field_structure_get_field_by_index(_struct
, i
);
799 ret
= BT_COMPONENT_STATUS_ERROR
;
802 if (bt_ctf_field_type_structure_get_field(struct_type
,
803 &field_name
, &field_type
, i
) < 0) {
804 ret
= BT_COMPONENT_STATUS_ERROR
;
809 fprintf(text
->out
, ", ");
811 fprintf(text
->out
, " ");
814 print_field_name_equal(text
, rem_(field_name
));
816 ret
= print_field(text
, field
, print_names
);
824 enum bt_component_status
print_struct(struct text_component
*text
,
825 struct bt_ctf_field
*_struct
, bool print_names
)
827 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
828 struct bt_ctf_field_type
*struct_type
= NULL
;
831 struct_type
= bt_ctf_field_get_type(_struct
);
833 ret
= BT_COMPONENT_STATUS_ERROR
;
836 nr_fields
= bt_ctf_field_type_structure_get_field_count(struct_type
);
838 ret
= BT_COMPONENT_STATUS_ERROR
;
841 fprintf(text
->out
, "{");
843 for (i
= 0; i
< nr_fields
; i
++) {
844 ret
= print_struct_field(text
, _struct
, struct_type
, i
,
846 if (ret
!= BT_COMPONENT_STATUS_OK
) {
851 fprintf(text
->out
, " }");
858 enum bt_component_status
print_array_field(struct text_component
*text
,
859 struct bt_ctf_field
*array
, uint64_t i
,
860 bool is_string
, bool print_names
)
862 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
863 struct bt_ctf_field
*field
= NULL
;
867 fprintf(text
->out
, ", ");
869 fprintf(text
->out
, " ");
872 field
= bt_ctf_field_array_get_field(array
, i
);
874 ret
= BT_COMPONENT_STATUS_ERROR
;
877 ret
= print_field(text
, field
, print_names
);
884 enum bt_component_status
print_array(struct text_component
*text
,
885 struct bt_ctf_field
*array
, bool print_names
)
887 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
888 struct bt_ctf_field_type
*array_type
= NULL
, *field_type
= NULL
;
889 enum bt_ctf_type_id type_id
;
892 bool is_string
= false;
894 array_type
= bt_ctf_field_get_type(array
);
896 ret
= BT_COMPONENT_STATUS_ERROR
;
899 field_type
= bt_ctf_field_type_array_get_element_type(array_type
);
901 ret
= BT_COMPONENT_STATUS_ERROR
;
904 len
= bt_ctf_field_type_array_get_length(array_type
);
906 ret
= BT_COMPONENT_STATUS_ERROR
;
909 type_id
= bt_ctf_field_type_get_type_id(field_type
);
910 if (type_id
== BT_CTF_TYPE_ID_INTEGER
) {
911 enum bt_ctf_string_encoding encoding
;
913 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
914 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
915 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
916 int integer_len
, integer_alignment
;
918 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
919 if (integer_len
< 0) {
920 return BT_COMPONENT_STATUS_ERROR
;
922 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
923 if (integer_alignment
< 0) {
924 return BT_COMPONENT_STATUS_ERROR
;
926 if (integer_len
== CHAR_BIT
927 && integer_alignment
== CHAR_BIT
) {
934 g_string_assign(text
->string
, "");
936 fprintf(text
->out
, "[");
940 for (i
= 0; i
< len
; i
++) {
941 ret
= print_array_field(text
, array
, i
, is_string
, print_names
);
942 if (ret
!= BT_COMPONENT_STATUS_OK
) {
949 if (text
->use_colors
) {
950 fputs(COLOR_STRING_VALUE
, text
->out
);
952 // TODO: escape string
953 fprintf(text
->out
, "\"%s\"", text
->string
->str
);
954 if (text
->use_colors
) {
955 fputs(COLOR_RST
, text
->out
);
958 fprintf(text
->out
, " ]");
967 enum bt_component_status
print_sequence_field(struct text_component
*text
,
968 struct bt_ctf_field
*seq
, uint64_t i
,
969 bool is_string
, bool print_names
)
971 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
972 struct bt_ctf_field
*field
= NULL
;
976 fprintf(text
->out
, ", ");
978 fprintf(text
->out
, " ");
981 field
= bt_ctf_field_sequence_get_field(seq
, i
);
983 ret
= BT_COMPONENT_STATUS_ERROR
;
986 ret
= print_field(text
, field
, print_names
);
993 enum bt_component_status
print_sequence(struct text_component
*text
,
994 struct bt_ctf_field
*seq
, bool print_names
)
996 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
997 struct bt_ctf_field_type
*seq_type
= NULL
, *field_type
= NULL
;
998 struct bt_ctf_field
*length_field
= NULL
;
999 enum bt_ctf_type_id type_id
;
1002 bool is_string
= false;
1004 seq_type
= bt_ctf_field_get_type(seq
);
1006 ret
= BT_COMPONENT_STATUS_ERROR
;
1009 length_field
= bt_ctf_field_sequence_get_length(seq
);
1010 if (!length_field
) {
1011 ret
= BT_COMPONENT_STATUS_ERROR
;
1014 if (bt_ctf_field_unsigned_integer_get_value(length_field
, &len
) < 0) {
1015 ret
= BT_COMPONENT_STATUS_ERROR
;
1018 field_type
= bt_ctf_field_type_sequence_get_element_type(seq_type
);
1020 ret
= BT_COMPONENT_STATUS_ERROR
;
1023 type_id
= bt_ctf_field_type_get_type_id(field_type
);
1024 if (type_id
== BT_CTF_TYPE_ID_INTEGER
) {
1025 enum bt_ctf_string_encoding encoding
;
1027 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
1028 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
1029 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
1030 int integer_len
, integer_alignment
;
1032 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
1033 if (integer_len
< 0) {
1034 ret
= BT_COMPONENT_STATUS_ERROR
;
1037 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1038 if (integer_alignment
< 0) {
1039 ret
= BT_COMPONENT_STATUS_ERROR
;
1042 if (integer_len
== CHAR_BIT
1043 && integer_alignment
== CHAR_BIT
) {
1050 g_string_assign(text
->string
, "");
1052 fprintf(text
->out
, "[");
1056 for (i
= 0; i
< len
; i
++) {
1057 ret
= print_sequence_field(text
, seq
, i
,
1058 is_string
, print_names
);
1059 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1066 if (text
->use_colors
) {
1067 fputs(COLOR_STRING_VALUE
, text
->out
);
1069 // TODO: escape string
1070 fprintf(text
->out
, "\"%s\"", text
->string
->str
);
1071 if (text
->use_colors
) {
1072 fputs(COLOR_RST
, text
->out
);
1075 fprintf(text
->out
, " ]");
1078 bt_put(length_field
);
1085 enum bt_component_status
print_variant(struct text_component
*text
,
1086 struct bt_ctf_field
*variant
, bool print_names
)
1088 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1089 struct bt_ctf_field
*field
= NULL
;
1091 field
= bt_ctf_field_variant_get_current_field(variant
);
1093 ret
= BT_COMPONENT_STATUS_ERROR
;
1096 fprintf(text
->out
, "{ ");
1100 struct bt_ctf_field
*tag_field
= NULL
;
1101 const char *tag_choice
;
1102 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
;
1104 tag_field
= bt_ctf_field_variant_get_tag(variant
);
1106 ret
= BT_COMPONENT_STATUS_ERROR
;
1110 iter
= bt_ctf_field_enumeration_get_mappings(tag_field
);
1113 ret
= BT_COMPONENT_STATUS_ERROR
;
1118 bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
1119 iter
, &tag_choice
, NULL
, NULL
);
1123 ret
= BT_COMPONENT_STATUS_ERROR
;
1126 print_field_name_equal(text
, rem_(tag_choice
));
1130 ret
= print_field(text
, field
, print_names
);
1131 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1135 fprintf(text
->out
, " }");
1142 enum bt_component_status
print_field(struct text_component
*text
,
1143 struct bt_ctf_field
*field
, bool print_names
)
1145 enum bt_ctf_type_id type_id
;
1147 type_id
= bt_ctf_field_get_type_id(field
);
1149 case CTF_TYPE_INTEGER
:
1150 return print_integer(text
, field
);
1151 case CTF_TYPE_FLOAT
:
1155 if (bt_ctf_field_floating_point_get_value(field
, &v
)) {
1156 return BT_COMPONENT_STATUS_ERROR
;
1158 if (text
->use_colors
) {
1159 fputs(COLOR_NUMBER_VALUE
, text
->out
);
1161 fprintf(text
->out
, "%g", v
);
1162 if (text
->use_colors
) {
1163 fputs(COLOR_RST
, text
->out
);
1165 return BT_COMPONENT_STATUS_OK
;
1168 return print_enum(text
, field
);
1169 case CTF_TYPE_STRING
:
1170 if (text
->use_colors
) {
1171 fputs(COLOR_STRING_VALUE
, text
->out
);
1173 // TODO: escape the string value
1174 fprintf(text
->out
, "\"%s\"",
1175 bt_ctf_field_string_get_value(field
));
1176 if (text
->use_colors
) {
1177 fputs(COLOR_RST
, text
->out
);
1179 return BT_COMPONENT_STATUS_OK
;
1180 case CTF_TYPE_STRUCT
:
1181 return print_struct(text
, field
, print_names
);
1182 case CTF_TYPE_UNTAGGED_VARIANT
:
1183 case CTF_TYPE_VARIANT
:
1184 return print_variant(text
, field
, print_names
);
1185 case CTF_TYPE_ARRAY
:
1186 return print_array(text
, field
, print_names
);
1187 case CTF_TYPE_SEQUENCE
:
1188 return print_sequence(text
, field
, print_names
);
1190 fprintf(text
->err
, "[error] Unknown type id: %d\n", (int) type_id
);
1191 return BT_COMPONENT_STATUS_ERROR
;
1196 enum bt_component_status
print_stream_packet_context(struct text_component
*text
,
1197 struct bt_ctf_event
*event
)
1199 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1200 struct bt_ctf_packet
*packet
= NULL
;
1201 struct bt_ctf_field
*main_field
= NULL
;
1203 packet
= bt_ctf_event_get_packet(event
);
1205 ret
= BT_COMPONENT_STATUS_ERROR
;
1208 main_field
= bt_ctf_packet_get_context(packet
);
1212 if (!text
->start_line
) {
1213 fputs(", ", text
->out
);
1215 text
->start_line
= false;
1216 if (text
->options
.print_scope_field_names
) {
1217 print_name_equal(text
, "stream.packet.context");
1219 ret
= print_field(text
, main_field
,
1220 text
->options
.print_context_field_names
);
1228 enum bt_component_status
print_event_header_raw(struct text_component
*text
,
1229 struct bt_ctf_event
*event
)
1231 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1232 struct bt_ctf_field
*main_field
= NULL
;
1234 main_field
= bt_ctf_event_get_header(event
);
1238 if (!text
->start_line
) {
1239 fputs(", ", text
->out
);
1241 text
->start_line
= false;
1242 if (text
->options
.print_scope_field_names
) {
1243 print_name_equal(text
, "stream.event.header");
1245 ret
= print_field(text
, main_field
,
1246 text
->options
.print_header_field_names
);
1253 enum bt_component_status
print_stream_event_context(struct text_component
*text
,
1254 struct bt_ctf_event
*event
)
1256 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1257 struct bt_ctf_field
*main_field
= NULL
;
1259 main_field
= bt_ctf_event_get_stream_event_context(event
);
1263 if (!text
->start_line
) {
1264 fputs(", ", text
->out
);
1266 text
->start_line
= false;
1267 if (text
->options
.print_scope_field_names
) {
1268 print_name_equal(text
, "stream.event.context");
1270 ret
= print_field(text
, main_field
,
1271 text
->options
.print_context_field_names
);
1278 enum bt_component_status
print_event_context(struct text_component
*text
,
1279 struct bt_ctf_event
*event
)
1281 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1282 struct bt_ctf_field
*main_field
= NULL
;
1284 main_field
= bt_ctf_event_get_event_context(event
);
1288 if (!text
->start_line
) {
1289 fputs(", ", text
->out
);
1291 text
->start_line
= false;
1292 if (text
->options
.print_scope_field_names
) {
1293 print_name_equal(text
, "event.context");
1295 ret
= print_field(text
, main_field
,
1296 text
->options
.print_context_field_names
);
1303 enum bt_component_status
print_event_payload(struct text_component
*text
,
1304 struct bt_ctf_event
*event
)
1306 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1307 struct bt_ctf_field
*main_field
= NULL
;
1309 main_field
= bt_ctf_event_get_payload_field(event
);
1313 if (!text
->start_line
) {
1314 fputs(", ", text
->out
);
1316 text
->start_line
= false;
1317 if (text
->options
.print_scope_field_names
) {
1318 print_name_equal(text
, "event.fields");
1320 ret
= print_field(text
, main_field
,
1321 text
->options
.print_payload_field_names
);
1328 enum bt_component_status
text_print_event(struct text_component
*text
,
1329 struct bt_ctf_event
*event
)
1331 enum bt_component_status ret
;
1333 text
->start_line
= true;
1334 ret
= print_event_header(text
, event
);
1335 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1339 ret
= print_stream_packet_context(text
, event
);
1340 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1344 ret
= print_event_header_raw(text
, event
);
1345 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1349 ret
= print_stream_event_context(text
, event
);
1350 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1354 ret
= print_event_context(text
, event
);
1355 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1359 ret
= print_event_payload(text
, event
);
1360 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1364 fputc('\n', text
->out
);