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-internal.h>
40 #include <babeltrace/common-internal.h>
45 #define NSEC_PER_SEC 1000000000LL
47 #define COLOR_NAME BT_COMMON_COLOR_BOLD
48 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
49 #define COLOR_RST BT_COMMON_COLOR_RESET
50 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
51 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
52 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
53 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
54 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
55 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
58 const char *rem_(const char *str
)
67 int64_t real_timestamp
; /* Relative to UNIX epoch. */
68 uint64_t clock_value
; /* In cycles. */
72 enum bt_component_status
print_field(struct text_component
*text
,
73 struct bt_ctf_field
*field
, bool print_names
,
74 GQuark
*filters_fields
, int filter_array_len
);
77 void print_name_equal(struct text_component
*text
, const char *name
)
79 if (text
->use_colors
) {
80 fprintf(text
->out
, "%s%s%s = ", COLOR_NAME
, name
, COLOR_RST
);
82 fprintf(text
->out
, "%s = ", name
);
87 void print_field_name_equal(struct text_component
*text
, const char *name
)
89 if (text
->use_colors
) {
90 fprintf(text
->out
, "%s%s%s = ", COLOR_FIELD_NAME
, name
,
93 fprintf(text
->out
, "%s = ", name
);
98 void print_timestamp_cycles(struct text_component
*text
,
99 struct bt_ctf_clock_class
*clock_class
,
100 struct bt_ctf_event
*event
)
103 struct bt_ctf_clock_value
*clock_value
;
106 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
108 fputs("????????????????????", text
->out
);
112 ret
= bt_ctf_clock_value_get_value(clock_value
, &cycles
);
115 fprintf(text
->out
, "Error");
118 fprintf(text
->out
, "%020" PRIu64
, cycles
);
120 if (text
->last_cycles_timestamp
!= -1ULL) {
121 text
->delta_cycles
= cycles
- text
->last_cycles_timestamp
;
123 text
->last_cycles_timestamp
= cycles
;
127 void print_timestamp_wall(struct text_component
*text
,
128 struct bt_ctf_clock_class
*clock_class
,
129 struct bt_ctf_event
*event
)
132 struct bt_ctf_clock_value
*clock_value
;
133 int64_t ts_nsec
= 0; /* add configurable offset */
134 int64_t ts_sec
= 0; /* add configurable offset */
135 uint64_t ts_sec_abs
, ts_nsec_abs
;
138 clock_value
= bt_ctf_event_get_clock_value(event
, clock_class
);
140 fputs("??:??:??.?????????", text
->out
);
144 ret
= bt_ctf_clock_value_get_value_ns_from_epoch(clock_value
, &ts_nsec
);
147 fprintf(text
->out
, "Error");
151 if (text
->last_real_timestamp
!= -1ULL) {
152 text
->delta_real_timestamp
= ts_nsec
- text
->last_real_timestamp
;
154 text
->last_real_timestamp
= ts_nsec
;
156 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
157 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
158 if (ts_sec
>= 0 && ts_nsec
>= 0) {
161 ts_nsec_abs
= ts_nsec
;
162 } else if (ts_sec
> 0 && ts_nsec
< 0) {
164 ts_sec_abs
= ts_sec
- 1;
165 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
166 } else if (ts_sec
== 0 && ts_nsec
< 0) {
169 ts_nsec_abs
= -ts_nsec
;
170 } else if (ts_sec
< 0 && ts_nsec
> 0) {
172 ts_sec_abs
= -(ts_sec
+ 1);
173 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
174 } else if (ts_sec
< 0 && ts_nsec
== 0) {
176 ts_sec_abs
= -ts_sec
;
177 ts_nsec_abs
= ts_nsec
;
178 } else { /* (ts_sec < 0 && ts_nsec < 0) */
180 ts_sec_abs
= -ts_sec
;
181 ts_nsec_abs
= -ts_nsec
;
184 if (!text
->options
.clock_seconds
) {
186 time_t time_s
= (time_t) ts_sec_abs
;
189 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
193 if (!text
->options
.clock_gmt
) {
196 res
= localtime_r(&time_s
, &tm
);
198 fprintf(stderr
, "[warning] Unable to get localtime.\n");
204 res
= gmtime_r(&time_s
, &tm
);
206 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
210 if (text
->options
.clock_date
) {
214 /* Print date and time */
215 res
= strftime(timestr
, sizeof(timestr
),
218 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
221 fprintf(text
->out
, "%s", timestr
);
223 /* Print time in HH:MM:SS.ns */
224 fprintf(text
->out
, "%02d:%02d:%02d.%09" PRIu64
,
225 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
, ts_nsec_abs
);
229 fprintf(text
->out
, "%s%" PRId64
".%09" PRIu64
,
230 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
236 enum bt_component_status
print_event_timestamp(struct text_component
*text
,
237 struct bt_ctf_event
*event
, bool *start_line
)
239 bool print_names
= text
->options
.print_header_field_names
;
240 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
241 struct bt_ctf_stream
*stream
= NULL
;
242 struct bt_ctf_stream_class
*stream_class
= NULL
;
243 struct bt_ctf_trace
*trace
= NULL
;
244 struct bt_ctf_clock_class
*clock_class
= NULL
;
245 FILE *out
= text
->out
;
247 stream
= bt_ctf_event_get_stream(event
);
249 ret
= BT_COMPONENT_STATUS_ERROR
;
253 stream_class
= bt_ctf_stream_get_class(stream
);
255 ret
= BT_COMPONENT_STATUS_ERROR
;
258 trace
= bt_ctf_stream_class_get_trace(stream_class
);
260 ret
= BT_COMPONENT_STATUS_ERROR
;
263 clock_class
= bt_ctf_trace_get_clock_class(trace
, 0);
265 ret
= BT_COMPONENT_STATUS_ERROR
;
270 print_name_equal(text
, "timestamp");
274 if (text
->use_colors
) {
275 fputs(COLOR_TIMESTAMP
, text
->out
);
277 if (text
->options
.print_timestamp_cycles
) {
278 print_timestamp_cycles(text
, clock_class
, event
);
280 print_timestamp_wall(text
, clock_class
, event
);
282 if (text
->use_colors
) {
283 fputs(COLOR_RST
, text
->out
);
289 if (text
->options
.print_delta_field
) {
291 fputs(", ", text
->out
);
292 print_name_equal(text
, "delta");
294 fputs("(", text
->out
);
296 if (text
->options
.print_timestamp_cycles
) {
297 if (text
->delta_cycles
== -1ULL) {
298 fputs("+??????????\?\?) ", text
->out
); /* Not a trigraph. */
300 fprintf(text
->out
, "+%012" PRIu64
, text
->delta_cycles
);
303 if (text
->delta_real_timestamp
!= -1ULL) {
304 uint64_t delta_sec
, delta_nsec
, delta
;
306 delta
= text
->delta_real_timestamp
;
307 delta_sec
= delta
/ NSEC_PER_SEC
;
308 delta_nsec
= delta
% NSEC_PER_SEC
;
309 fprintf(text
->out
, "+%" PRIu64
".%09" PRIu64
,
310 delta_sec
, delta_nsec
);
312 fputs("+?.?????????", text
->out
);
316 fputs(") ", text
->out
);
319 *start_line
= !print_names
;
324 bt_put(stream_class
);
330 enum bt_component_status
print_event_header(struct text_component
*text
,
331 struct bt_ctf_event
*event
)
333 bool print_names
= text
->options
.print_header_field_names
;
334 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
335 struct bt_ctf_event_class
*event_class
= NULL
;
336 struct bt_ctf_stream_class
*stream_class
= NULL
;
337 struct bt_ctf_trace
*trace_class
= NULL
;
340 event_class
= bt_ctf_event_get_class(event
);
342 ret
= BT_COMPONENT_STATUS_ERROR
;
345 stream_class
= bt_ctf_event_class_get_stream_class(event_class
);
347 ret
= BT_COMPONENT_STATUS_ERROR
;
350 trace_class
= bt_ctf_stream_class_get_trace(stream_class
);
352 ret
= BT_COMPONENT_STATUS_ERROR
;
355 ret
= print_event_timestamp(text
, event
, &text
->start_line
);
356 if (ret
!= BT_COMPONENT_STATUS_OK
) {
359 if (text
->options
.print_trace_field
) {
362 name
= bt_ctf_trace_get_name(trace_class
);
364 if (!text
->start_line
) {
365 fputs(", ", text
->out
);
368 print_name_equal(text
, "trace");
370 fprintf(text
->out
, "%s", name
);
372 fprintf(text
->out
, " ");
376 if (text
->options
.print_trace_hostname_field
) {
377 struct bt_value
*hostname_str
;
379 hostname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
384 if (!text
->start_line
) {
385 fputs(", ", text
->out
);
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
);
398 if (text
->options
.print_trace_domain_field
) {
399 struct bt_value
*domain_str
;
401 domain_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
406 if (!text
->start_line
) {
407 fputs(", ", text
->out
);
410 print_name_equal(text
, "trace:domain");
411 } else if (dom_print
) {
412 fputs(":", text
->out
);
414 if (bt_value_string_get(domain_str
, &str
)
415 == BT_VALUE_STATUS_OK
) {
416 fprintf(text
->out
, "%s", str
);
422 if (text
->options
.print_trace_procname_field
) {
423 struct bt_value
*procname_str
;
425 procname_str
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
430 if (!text
->start_line
) {
431 fputs(", ", text
->out
);
434 print_name_equal(text
, "trace:procname");
435 } else if (dom_print
) {
436 fputs(":", text
->out
);
438 if (bt_value_string_get(procname_str
, &str
)
439 == BT_VALUE_STATUS_OK
) {
440 fprintf(text
->out
, "%s", str
);
442 bt_put(procname_str
);
446 if (text
->options
.print_trace_vpid_field
) {
447 struct bt_value
*vpid_value
;
449 vpid_value
= bt_ctf_trace_get_environment_field_value_by_name(trace_class
,
454 if (!text
->start_line
) {
455 fputs(", ", text
->out
);
458 print_name_equal(text
, "trace:vpid");
459 } else if (dom_print
) {
460 fputs(":", text
->out
);
462 if (bt_value_integer_get(vpid_value
, &value
)
463 == BT_VALUE_STATUS_OK
) {
464 fprintf(text
->out
, "(%" PRId64
")", value
);
470 if (text
->options
.print_loglevel_field
) {
471 struct bt_value
*loglevel_str
, *loglevel_value
;
473 loglevel_str
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
475 loglevel_value
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
477 if (loglevel_str
|| loglevel_value
) {
478 bool has_str
= false;
480 if (!text
->start_line
) {
481 fputs(", ", text
->out
);
484 print_name_equal(text
, "loglevel");
485 } else if (dom_print
) {
486 fputs(":", text
->out
);
491 if (bt_value_string_get(loglevel_str
, &str
)
492 == BT_VALUE_STATUS_OK
) {
493 fprintf(text
->out
, "%s", str
);
497 if (loglevel_value
) {
500 if (bt_value_integer_get(loglevel_value
, &value
)
501 == BT_VALUE_STATUS_OK
) {
502 fprintf(text
->out
, "%s(%" PRId64
")",
503 has_str
? " " : "", value
);
506 bt_put(loglevel_str
);
507 bt_put(loglevel_value
);
511 if (text
->options
.print_emf_field
) {
512 struct bt_value
*uri_str
;
514 uri_str
= bt_ctf_event_class_get_attribute_value_by_name(event_class
,
517 if (!text
->start_line
) {
518 fputs(", ", text
->out
);
521 print_name_equal(text
, "model.emf.uri");
522 } else if (dom_print
) {
523 fputs(":", text
->out
);
528 if (bt_value_string_get(uri_str
, &str
)
529 == BT_VALUE_STATUS_OK
) {
530 fprintf(text
->out
, "%s", str
);
537 if (dom_print
&& !print_names
) {
538 fputs(" ", text
->out
);
540 if (!text
->start_line
) {
541 fputs(", ", text
->out
);
543 text
->start_line
= true;
545 print_name_equal(text
, "name");
547 if (text
->use_colors
) {
548 fputs(COLOR_EVENT_NAME
, text
->out
);
550 fputs(bt_ctf_event_class_get_name(event_class
), text
->out
);
551 if (text
->use_colors
) {
552 fputs(COLOR_RST
, text
->out
);
555 fputs(": ", text
->out
);
557 fputs(", ", text
->out
);
561 bt_put(stream_class
);
567 enum bt_component_status
print_integer(struct text_component
*text
,
568 struct bt_ctf_field
*field
)
570 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
571 struct bt_ctf_field_type
*field_type
= NULL
;
572 enum bt_ctf_integer_base base
;
573 enum bt_ctf_string_encoding encoding
;
579 bool rst_color
= false;
581 field_type
= bt_ctf_field_get_type(field
);
583 ret
= BT_COMPONENT_STATUS_ERROR
;
586 signedness
= bt_ctf_field_type_integer_get_signed(field_type
);
587 if (signedness
< 0) {
588 ret
= BT_COMPONENT_STATUS_ERROR
;
592 if (bt_ctf_field_unsigned_integer_get_value(field
, &v
.u
) < 0) {
593 ret
= BT_COMPONENT_STATUS_ERROR
;
597 if (bt_ctf_field_signed_integer_get_value(field
, &v
.s
) < 0) {
598 ret
= BT_COMPONENT_STATUS_ERROR
;
603 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
605 case BT_CTF_STRING_ENCODING_UTF8
:
606 case BT_CTF_STRING_ENCODING_ASCII
:
607 g_string_append_c(text
->string
, (int) v
.u
);
609 case BT_CTF_STRING_ENCODING_NONE
:
610 case BT_CTF_STRING_ENCODING_UNKNOWN
:
613 ret
= BT_COMPONENT_STATUS_ERROR
;
617 if (text
->use_colors
) {
618 fputs(COLOR_NUMBER_VALUE
, text
->out
);
622 base
= bt_ctf_field_type_integer_get_base(field_type
);
624 case BT_CTF_INTEGER_BASE_BINARY
:
628 len
= bt_ctf_field_type_integer_get_size(field_type
);
630 ret
= BT_COMPONENT_STATUS_ERROR
;
633 fprintf(text
->out
, "0b");
634 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
635 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
636 fprintf(text
->out
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
637 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
641 case BT_CTF_INTEGER_BASE_OCTAL
:
646 len
= bt_ctf_field_type_integer_get_size(field_type
);
648 ret
= BT_COMPONENT_STATUS_ERROR
;
655 /* Round length to the nearest 3-bit */
656 rounded_len
= (((len
- 1) / 3) + 1) * 3;
657 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
661 fprintf(text
->out
, "0%" PRIo64
, v
.u
);
664 case BT_CTF_INTEGER_BASE_DECIMAL
:
666 fprintf(text
->out
, "%" PRIu64
, v
.u
);
668 fprintf(text
->out
, "%" PRId64
, v
.s
);
671 case BT_CTF_INTEGER_BASE_HEXADECIMAL
:
675 len
= bt_ctf_field_type_integer_get_size(field_type
);
677 ret
= BT_COMPONENT_STATUS_ERROR
;
681 /* Round length to the nearest nibble */
682 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
684 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
687 fprintf(text
->out
, "0x%" PRIX64
, v
.u
);
691 ret
= BT_COMPONENT_STATUS_ERROR
;
696 fputs(COLOR_RST
, text
->out
);
703 void print_escape_string(struct text_component
*text
, const char *str
)
707 fputc('"', text
->out
);
708 for (i
= 0; i
< strlen(str
); i
++) {
709 /* Escape sequences not recognized by iscntrl(). */
712 fputs("\\\\", text
->out
);
715 fputs("\\\'", text
->out
);
718 fputs("\\\"", text
->out
);
721 fputs("\\\?", text
->out
);
725 /* Standard characters. */
726 if (!iscntrl(str
[i
])) {
727 fputc(str
[i
], text
->out
);
733 fputs("\\0", text
->out
);
736 fputs("\\a", text
->out
);
739 fputs("\\b", text
->out
);
742 fputs("\\e", text
->out
);
745 fputs("\\f", text
->out
);
748 fputs("\\n", text
->out
);
751 fputs("\\r", text
->out
);
754 fputs("\\t", text
->out
);
757 fputs("\\v", text
->out
);
760 /* Unhandled control-sequence, print as hex. */
761 fprintf(text
->out
, "\\x%02x", str
[i
]);
765 fputc('"', text
->out
);
769 enum bt_component_status
print_enum(struct text_component
*text
,
770 struct bt_ctf_field
*field
)
772 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
773 struct bt_ctf_field
*container_field
= NULL
;
774 struct bt_ctf_field_type
*enumeration_field_type
= NULL
;
775 struct bt_ctf_field_type
*container_field_type
= NULL
;
776 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
= NULL
;
780 enumeration_field_type
= bt_ctf_field_get_type(field
);
781 if (!enumeration_field_type
) {
782 ret
= BT_COMPONENT_STATUS_ERROR
;
785 container_field
= bt_ctf_field_enumeration_get_container(field
);
786 if (!container_field
) {
787 ret
= BT_COMPONENT_STATUS_ERROR
;
790 container_field_type
= bt_ctf_field_get_type(container_field
);
791 if (!container_field_type
) {
792 ret
= BT_COMPONENT_STATUS_ERROR
;
795 is_signed
= bt_ctf_field_type_integer_get_signed(container_field_type
);
797 ret
= BT_COMPONENT_STATUS_ERROR
;
803 if (bt_ctf_field_signed_integer_get_value(container_field
,
805 ret
= BT_COMPONENT_STATUS_ERROR
;
808 iter
= bt_ctf_field_type_enumeration_find_mappings_by_signed_value(
809 enumeration_field_type
, value
);
813 if (bt_ctf_field_unsigned_integer_get_value(container_field
,
815 ret
= BT_COMPONENT_STATUS_ERROR
;
818 iter
= bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(
819 enumeration_field_type
, value
);
822 ret
= BT_COMPONENT_STATUS_ERROR
;
825 fprintf(text
->out
, "( ");
827 const char *mapping_name
;
829 if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
830 iter
, &mapping_name
, NULL
, NULL
) < 0) {
831 ret
= BT_COMPONENT_STATUS_ERROR
;
835 fprintf(text
->out
, ", ");
836 if (text
->use_colors
) {
837 fputs(COLOR_ENUM_MAPPING_NAME
, text
->out
);
839 print_escape_string(text
, mapping_name
);
840 if (text
->use_colors
) {
841 fputs(COLOR_RST
, text
->out
);
843 if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter
) < 0) {
848 if (text
->use_colors
) {
849 fputs(COLOR_UNKNOWN
, text
->out
);
851 fprintf(text
->out
, "<unknown>");
852 if (text
->use_colors
) {
853 fputs(COLOR_RST
, text
->out
);
856 fprintf(text
->out
, " : container = ");
857 ret
= print_integer(text
, container_field
);
858 if (ret
!= BT_COMPONENT_STATUS_OK
) {
861 fprintf(text
->out
, " )");
864 bt_put(container_field_type
);
865 bt_put(container_field
);
866 bt_put(enumeration_field_type
);
871 int filter_field_name(struct text_component
*text
, const char *field_name
,
872 GQuark
*filter_fields
, int filter_array_len
)
875 GQuark field_quark
= g_quark_try_string(field_name
);
877 if (!field_quark
|| text
->options
.verbose
) {
881 for (i
= 0; i
< filter_array_len
; i
++) {
882 if (field_quark
== filter_fields
[i
]) {
890 enum bt_component_status
print_struct_field(struct text_component
*text
,
891 struct bt_ctf_field
*_struct
,
892 struct bt_ctf_field_type
*struct_type
,
893 int i
, bool print_names
, int *nr_printed_fields
,
894 GQuark
*filter_fields
, int filter_array_len
)
896 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
897 const char *field_name
;
898 struct bt_ctf_field
*field
= NULL
;
899 struct bt_ctf_field_type
*field_type
= NULL
;;
901 field
= bt_ctf_field_structure_get_field_by_index(_struct
, i
);
903 ret
= BT_COMPONENT_STATUS_ERROR
;
906 if (bt_ctf_field_type_structure_get_field(struct_type
,
907 &field_name
, &field_type
, i
) < 0) {
908 ret
= BT_COMPONENT_STATUS_ERROR
;
912 if (filter_fields
&& !filter_field_name(text
, field_name
,
913 filter_fields
, filter_array_len
)) {
914 ret
= BT_COMPONENT_STATUS_OK
;
918 if (*nr_printed_fields
> 0) {
919 fprintf(text
->out
, ", ");
921 fprintf(text
->out
, " ");
924 print_field_name_equal(text
, rem_(field_name
));
926 ret
= print_field(text
, field
, print_names
, NULL
, 0);
927 *nr_printed_fields
+= 1;
935 enum bt_component_status
print_struct(struct text_component
*text
,
936 struct bt_ctf_field
*_struct
, bool print_names
,
937 GQuark
*filter_fields
, int filter_array_len
)
939 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
940 struct bt_ctf_field_type
*struct_type
= NULL
;
941 int nr_fields
, i
, nr_printed_fields
;
943 struct_type
= bt_ctf_field_get_type(_struct
);
945 ret
= BT_COMPONENT_STATUS_ERROR
;
948 nr_fields
= bt_ctf_field_type_structure_get_field_count(struct_type
);
950 ret
= BT_COMPONENT_STATUS_ERROR
;
953 fprintf(text
->out
, "{");
955 nr_printed_fields
= 0;
956 for (i
= 0; i
< nr_fields
; i
++) {
957 ret
= print_struct_field(text
, _struct
, struct_type
, i
,
958 print_names
, &nr_printed_fields
, filter_fields
,
960 if (ret
!= BT_COMPONENT_STATUS_OK
) {
965 fprintf(text
->out
, " }");
972 enum bt_component_status
print_array_field(struct text_component
*text
,
973 struct bt_ctf_field
*array
, uint64_t i
,
974 bool is_string
, bool print_names
)
976 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
977 struct bt_ctf_field
*field
= NULL
;
981 fprintf(text
->out
, ", ");
983 fprintf(text
->out
, " ");
986 fprintf(text
->out
, "[%" PRIu64
"] = ", i
);
989 field
= bt_ctf_field_array_get_field(array
, i
);
991 ret
= BT_COMPONENT_STATUS_ERROR
;
994 ret
= print_field(text
, field
, print_names
, NULL
, 0);
1001 enum bt_component_status
print_array(struct text_component
*text
,
1002 struct bt_ctf_field
*array
, bool print_names
)
1004 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1005 struct bt_ctf_field_type
*array_type
= NULL
, *field_type
= NULL
;
1006 enum bt_ctf_field_type_id type_id
;
1009 bool is_string
= false;
1011 array_type
= bt_ctf_field_get_type(array
);
1013 ret
= BT_COMPONENT_STATUS_ERROR
;
1016 field_type
= bt_ctf_field_type_array_get_element_type(array_type
);
1018 ret
= BT_COMPONENT_STATUS_ERROR
;
1021 len
= bt_ctf_field_type_array_get_length(array_type
);
1023 ret
= BT_COMPONENT_STATUS_ERROR
;
1026 type_id
= bt_ctf_field_type_get_type_id(field_type
);
1027 if (type_id
== BT_CTF_FIELD_TYPE_ID_INTEGER
) {
1028 enum bt_ctf_string_encoding encoding
;
1030 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
1031 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
1032 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
1033 int integer_len
, integer_alignment
;
1035 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
1036 if (integer_len
< 0) {
1037 return BT_COMPONENT_STATUS_ERROR
;
1039 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1040 if (integer_alignment
< 0) {
1041 return BT_COMPONENT_STATUS_ERROR
;
1043 if (integer_len
== CHAR_BIT
1044 && integer_alignment
== CHAR_BIT
) {
1051 g_string_assign(text
->string
, "");
1053 fprintf(text
->out
, "[");
1057 for (i
= 0; i
< len
; i
++) {
1058 ret
= print_array_field(text
, array
, i
, is_string
, print_names
);
1059 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1066 if (text
->use_colors
) {
1067 fputs(COLOR_STRING_VALUE
, text
->out
);
1069 print_escape_string(text
, text
->string
->str
);
1070 if (text
->use_colors
) {
1071 fputs(COLOR_RST
, text
->out
);
1074 fprintf(text
->out
, " ]");
1083 enum bt_component_status
print_sequence_field(struct text_component
*text
,
1084 struct bt_ctf_field
*seq
, uint64_t i
,
1085 bool is_string
, bool print_names
)
1087 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1088 struct bt_ctf_field
*field
= NULL
;
1092 fprintf(text
->out
, ", ");
1094 fprintf(text
->out
, " ");
1097 fprintf(text
->out
, "[%" PRIu64
"] = ", i
);
1100 field
= bt_ctf_field_sequence_get_field(seq
, i
);
1102 ret
= BT_COMPONENT_STATUS_ERROR
;
1105 ret
= print_field(text
, field
, print_names
, NULL
, 0);
1112 enum bt_component_status
print_sequence(struct text_component
*text
,
1113 struct bt_ctf_field
*seq
, bool print_names
)
1115 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1116 struct bt_ctf_field_type
*seq_type
= NULL
, *field_type
= NULL
;
1117 struct bt_ctf_field
*length_field
= NULL
;
1118 enum bt_ctf_field_type_id type_id
;
1121 bool is_string
= false;
1123 seq_type
= bt_ctf_field_get_type(seq
);
1125 ret
= BT_COMPONENT_STATUS_ERROR
;
1128 length_field
= bt_ctf_field_sequence_get_length(seq
);
1129 if (!length_field
) {
1130 ret
= BT_COMPONENT_STATUS_ERROR
;
1133 if (bt_ctf_field_unsigned_integer_get_value(length_field
, &len
) < 0) {
1134 ret
= BT_COMPONENT_STATUS_ERROR
;
1137 field_type
= bt_ctf_field_type_sequence_get_element_type(seq_type
);
1139 ret
= BT_COMPONENT_STATUS_ERROR
;
1142 type_id
= bt_ctf_field_type_get_type_id(field_type
);
1143 if (type_id
== BT_CTF_FIELD_TYPE_ID_INTEGER
) {
1144 enum bt_ctf_string_encoding encoding
;
1146 encoding
= bt_ctf_field_type_integer_get_encoding(field_type
);
1147 if (encoding
== BT_CTF_STRING_ENCODING_UTF8
1148 || encoding
== BT_CTF_STRING_ENCODING_ASCII
) {
1149 int integer_len
, integer_alignment
;
1151 integer_len
= bt_ctf_field_type_integer_get_size(field_type
);
1152 if (integer_len
< 0) {
1153 ret
= BT_COMPONENT_STATUS_ERROR
;
1156 integer_alignment
= bt_ctf_field_type_get_alignment(field_type
);
1157 if (integer_alignment
< 0) {
1158 ret
= BT_COMPONENT_STATUS_ERROR
;
1161 if (integer_len
== CHAR_BIT
1162 && integer_alignment
== CHAR_BIT
) {
1169 g_string_assign(text
->string
, "");
1171 fprintf(text
->out
, "[");
1175 for (i
= 0; i
< len
; i
++) {
1176 ret
= print_sequence_field(text
, seq
, i
,
1177 is_string
, print_names
);
1178 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1185 if (text
->use_colors
) {
1186 fputs(COLOR_STRING_VALUE
, text
->out
);
1188 print_escape_string(text
, text
->string
->str
);
1189 if (text
->use_colors
) {
1190 fputs(COLOR_RST
, text
->out
);
1193 fprintf(text
->out
, " ]");
1196 bt_put(length_field
);
1203 enum bt_component_status
print_variant(struct text_component
*text
,
1204 struct bt_ctf_field
*variant
, bool print_names
)
1206 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1207 struct bt_ctf_field
*field
= NULL
;
1209 field
= bt_ctf_field_variant_get_current_field(variant
);
1211 ret
= BT_COMPONENT_STATUS_ERROR
;
1214 fprintf(text
->out
, "{ ");
1218 struct bt_ctf_field
*tag_field
= NULL
;
1219 const char *tag_choice
;
1220 struct bt_ctf_field_type_enumeration_mapping_iterator
*iter
;
1222 tag_field
= bt_ctf_field_variant_get_tag(variant
);
1224 ret
= BT_COMPONENT_STATUS_ERROR
;
1228 iter
= bt_ctf_field_enumeration_get_mappings(tag_field
);
1231 ret
= BT_COMPONENT_STATUS_ERROR
;
1236 bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
1237 iter
, &tag_choice
, NULL
, NULL
);
1241 ret
= BT_COMPONENT_STATUS_ERROR
;
1244 print_field_name_equal(text
, rem_(tag_choice
));
1248 ret
= print_field(text
, field
, print_names
, NULL
, 0);
1249 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1253 fprintf(text
->out
, " }");
1260 enum bt_component_status
print_field(struct text_component
*text
,
1261 struct bt_ctf_field
*field
, bool print_names
,
1262 GQuark
*filter_fields
, int filter_array_len
)
1264 enum bt_ctf_field_type_id type_id
;
1266 type_id
= bt_ctf_field_get_type_id(field
);
1268 case CTF_TYPE_INTEGER
:
1269 return print_integer(text
, field
);
1270 case CTF_TYPE_FLOAT
:
1274 if (bt_ctf_field_floating_point_get_value(field
, &v
)) {
1275 return BT_COMPONENT_STATUS_ERROR
;
1277 if (text
->use_colors
) {
1278 fputs(COLOR_NUMBER_VALUE
, text
->out
);
1280 fprintf(text
->out
, "%g", v
);
1281 if (text
->use_colors
) {
1282 fputs(COLOR_RST
, text
->out
);
1284 return BT_COMPONENT_STATUS_OK
;
1287 return print_enum(text
, field
);
1288 case CTF_TYPE_STRING
:
1289 if (text
->use_colors
) {
1290 fputs(COLOR_STRING_VALUE
, text
->out
);
1292 print_escape_string(text
, bt_ctf_field_string_get_value(field
));
1293 if (text
->use_colors
) {
1294 fputs(COLOR_RST
, text
->out
);
1296 return BT_COMPONENT_STATUS_OK
;
1297 case CTF_TYPE_STRUCT
:
1298 return print_struct(text
, field
, print_names
, filter_fields
,
1300 case CTF_TYPE_UNTAGGED_VARIANT
:
1301 case CTF_TYPE_VARIANT
:
1302 return print_variant(text
, field
, print_names
);
1303 case CTF_TYPE_ARRAY
:
1304 return print_array(text
, field
, print_names
);
1305 case CTF_TYPE_SEQUENCE
:
1306 return print_sequence(text
, field
, print_names
);
1308 fprintf(text
->err
, "[error] Unknown type id: %d\n", (int) type_id
);
1309 return BT_COMPONENT_STATUS_ERROR
;
1314 enum bt_component_status
print_stream_packet_context(struct text_component
*text
,
1315 struct bt_ctf_event
*event
)
1317 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1318 struct bt_ctf_packet
*packet
= NULL
;
1319 struct bt_ctf_field
*main_field
= NULL
;
1321 packet
= bt_ctf_event_get_packet(event
);
1323 ret
= BT_COMPONENT_STATUS_ERROR
;
1326 main_field
= bt_ctf_packet_get_context(packet
);
1330 if (!text
->start_line
) {
1331 fputs(", ", text
->out
);
1333 text
->start_line
= false;
1334 if (text
->options
.print_scope_field_names
) {
1335 print_name_equal(text
, "stream.packet.context");
1337 ret
= print_field(text
, main_field
,
1338 text
->options
.print_context_field_names
,
1339 stream_packet_context_quarks
,
1340 STREAM_PACKET_CONTEXT_QUARKS_LEN
);
1348 enum bt_component_status
print_event_header_raw(struct text_component
*text
,
1349 struct bt_ctf_event
*event
)
1351 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1352 struct bt_ctf_field
*main_field
= NULL
;
1354 main_field
= bt_ctf_event_get_header(event
);
1358 if (!text
->start_line
) {
1359 fputs(", ", text
->out
);
1361 text
->start_line
= false;
1362 if (text
->options
.print_scope_field_names
) {
1363 print_name_equal(text
, "stream.event.header");
1365 ret
= print_field(text
, main_field
,
1366 text
->options
.print_header_field_names
, NULL
, 0);
1373 enum bt_component_status
print_stream_event_context(struct text_component
*text
,
1374 struct bt_ctf_event
*event
)
1376 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1377 struct bt_ctf_field
*main_field
= NULL
;
1379 main_field
= bt_ctf_event_get_stream_event_context(event
);
1383 if (!text
->start_line
) {
1384 fputs(", ", text
->out
);
1386 text
->start_line
= false;
1387 if (text
->options
.print_scope_field_names
) {
1388 print_name_equal(text
, "stream.event.context");
1390 ret
= print_field(text
, main_field
,
1391 text
->options
.print_context_field_names
, NULL
, 0);
1398 enum bt_component_status
print_event_context(struct text_component
*text
,
1399 struct bt_ctf_event
*event
)
1401 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1402 struct bt_ctf_field
*main_field
= NULL
;
1404 main_field
= bt_ctf_event_get_event_context(event
);
1408 if (!text
->start_line
) {
1409 fputs(", ", text
->out
);
1411 text
->start_line
= false;
1412 if (text
->options
.print_scope_field_names
) {
1413 print_name_equal(text
, "event.context");
1415 ret
= print_field(text
, main_field
,
1416 text
->options
.print_context_field_names
, NULL
, 0);
1423 enum bt_component_status
print_event_payload(struct text_component
*text
,
1424 struct bt_ctf_event
*event
)
1426 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1427 struct bt_ctf_field
*main_field
= NULL
;
1429 main_field
= bt_ctf_event_get_payload_field(event
);
1433 if (!text
->start_line
) {
1434 fputs(", ", text
->out
);
1436 text
->start_line
= false;
1437 if (text
->options
.print_scope_field_names
) {
1438 print_name_equal(text
, "event.fields");
1440 ret
= print_field(text
, main_field
,
1441 text
->options
.print_payload_field_names
, NULL
, 0);
1448 enum bt_component_status
text_print_event(struct text_component
*text
,
1449 struct bt_ctf_event
*event
)
1451 enum bt_component_status ret
;
1453 text
->start_line
= true;
1454 ret
= print_event_header(text
, event
);
1455 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1459 ret
= print_stream_packet_context(text
, event
);
1460 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1464 if (text
->options
.verbose
) {
1465 ret
= print_event_header_raw(text
, event
);
1466 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1471 ret
= print_stream_event_context(text
, event
);
1472 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1476 ret
= print_event_context(text
, event
);
1477 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1481 ret
= print_event_payload(text
, event
);
1482 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1486 fputc('\n', text
->out
);