2 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include <babeltrace2/babeltrace.h>
27 #include "common/assert.h"
28 #include "common/common.h"
31 #include "obj-lifetime-mgmt.h"
35 const char *plural(uint64_t value
)
37 return value
== 1 ? "" : "s";
41 void incr_indent_by(struct details_write_ctx
*ctx
, unsigned int value
)
44 ctx
->indent_level
+= value
;
48 void incr_indent(struct details_write_ctx
*ctx
)
50 incr_indent_by(ctx
, 2);
54 void decr_indent_by(struct details_write_ctx
*ctx
, unsigned int value
)
57 BT_ASSERT(ctx
->indent_level
>= value
);
58 ctx
->indent_level
-= value
;
62 void decr_indent(struct details_write_ctx
*ctx
)
64 decr_indent_by(ctx
, 2);
68 void format_uint(char *buf
, uint64_t value
, unsigned int base
)
70 const char *spec
= "%" PRIu64
;
71 char *buf_start
= buf
;
72 unsigned int digits_per_group
= 3;
74 bool sep_digits
= true;
79 /* TODO: Support binary format */
95 * Do not insert digit separators for numbers
96 * under 10,000 as it looks weird.
106 sprintf(buf_start
, spec
, value
);
109 bt_common_sep_digits(buf_start
, digits_per_group
, sep
);
114 void format_int(char *buf
, int64_t value
, unsigned int base
)
116 const char *spec
= "%" PRIu64
;
117 char *buf_start
= buf
;
118 unsigned int digits_per_group
= 3;
120 bool sep_digits
= true;
121 uint64_t abs_value
= value
< 0 ? (uint64_t) -value
: (uint64_t) value
;
131 /* TODO: Support binary format */
133 strcpy(buf_start
, "0x");
135 digits_per_group
= 4;
140 strcpy(buf_start
, "0");
145 if (value
>= -9999 && value
<= 9999) {
147 * Do not insert digit separators for numbers
148 * over -10,000 and under 10,000 as it looks
159 sprintf(buf_start
, spec
, abs_value
);
162 bt_common_sep_digits(buf_start
, digits_per_group
, sep
);
167 void write_nl(struct details_write_ctx
*ctx
)
170 g_string_append_c(ctx
->str
, '\n');
174 void write_sp(struct details_write_ctx
*ctx
)
177 g_string_append_c(ctx
->str
, ' ');
181 void write_indent(struct details_write_ctx
*ctx
)
187 for (i
= 0; i
< ctx
->indent_level
; i
++) {
193 void write_compound_member_name(struct details_write_ctx
*ctx
, const char *name
)
196 g_string_append_printf(ctx
->str
, "%s%s%s:",
197 color_fg_cyan(ctx
), name
, color_reset(ctx
));
201 void write_array_index(struct details_write_ctx
*ctx
, uint64_t index
)
206 format_uint(buf
, index
, 10);
207 g_string_append_printf(ctx
->str
, "%s[%s]%s:",
208 color_fg_cyan(ctx
), buf
, color_reset(ctx
));
212 void write_obj_type_name(struct details_write_ctx
*ctx
, const char *name
)
214 g_string_append_printf(ctx
->str
, "%s%s%s%s",
215 color_fg_yellow(ctx
), color_bold(ctx
), name
, color_reset(ctx
));
219 void write_prop_name(struct details_write_ctx
*ctx
, const char *prop_name
)
221 g_string_append_printf(ctx
->str
, "%s%s%s",
222 color_fg_magenta(ctx
), prop_name
, color_reset(ctx
));
226 void write_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
228 g_string_append_printf(ctx
->str
, "%s%s%s",
229 color_bold(ctx
), value
, color_reset(ctx
));
233 void write_uint_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
235 write_str_prop_value(ctx
, value
);
239 void write_uint_prop_value(struct details_write_ctx
*ctx
, uint64_t value
)
243 format_uint(buf
, value
, 10);
244 write_uint_str_prop_value(ctx
, buf
);
248 void write_int_prop_value(struct details_write_ctx
*ctx
, int64_t value
)
252 format_int(buf
, value
, 10);
253 write_uint_str_prop_value(ctx
, buf
);
257 void write_float_prop_value(struct details_write_ctx
*ctx
, double value
)
259 g_string_append_printf(ctx
->str
, "%s%f%s",
260 color_bold(ctx
), value
, color_reset(ctx
));
264 void write_str_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
265 const char *prop_value
)
267 BT_ASSERT(prop_value
);
269 write_prop_name(ctx
, prop_name
);
270 g_string_append(ctx
->str
, ": ");
271 write_str_prop_value(ctx
, prop_value
);
276 void write_uint_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
280 write_prop_name(ctx
, prop_name
);
281 g_string_append(ctx
->str
, ": ");
282 write_uint_prop_value(ctx
, prop_value
);
287 void write_int_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
291 write_prop_name(ctx
, prop_name
);
292 g_string_append(ctx
->str
, ": ");
293 write_int_prop_value(ctx
, prop_value
);
298 void write_int_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
300 write_str_prop_value(ctx
, value
);
304 void write_bool_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
310 write_prop_name(ctx
, prop_name
);
311 g_string_append_printf(ctx
->str
, ": %s", color_bold(ctx
));
314 g_string_append(ctx
->str
, color_fg_green(ctx
));
317 g_string_append(ctx
->str
, color_fg_red(ctx
));
321 g_string_append_printf(ctx
->str
, "%s%s\n", str
, color_reset(ctx
));
325 void write_uuid_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
330 write_prop_name(ctx
, prop_name
);
331 g_string_append_printf(ctx
->str
,
332 ": %s%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%s\n",
334 (unsigned int) uuid
[0],
335 (unsigned int) uuid
[1],
336 (unsigned int) uuid
[2],
337 (unsigned int) uuid
[3],
338 (unsigned int) uuid
[4],
339 (unsigned int) uuid
[5],
340 (unsigned int) uuid
[6],
341 (unsigned int) uuid
[7],
342 (unsigned int) uuid
[8],
343 (unsigned int) uuid
[9],
344 (unsigned int) uuid
[10],
345 (unsigned int) uuid
[11],
346 (unsigned int) uuid
[12],
347 (unsigned int) uuid
[13],
348 (unsigned int) uuid
[14],
349 (unsigned int) uuid
[15],
354 void write_int_field_class_props(struct details_write_ctx
*ctx
,
355 const bt_field_class
*fc
, bool close
)
357 g_string_append_printf(ctx
->str
, "(%s%" PRIu64
"-bit%s, Base ",
359 bt_field_class_integer_get_field_value_range(fc
),
362 switch (bt_field_class_integer_get_preferred_display_base(fc
)) {
363 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
364 write_uint_prop_value(ctx
, 2);
366 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
367 write_uint_prop_value(ctx
, 8);
369 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
370 write_uint_prop_value(ctx
, 10);
372 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
373 write_uint_prop_value(ctx
, 16);
380 g_string_append(ctx
->str
, ")");
384 struct enum_field_class_mapping_range
{
396 struct enum_field_class_mapping
{
400 /* Array of `struct enum_field_class_mapping_range` */
405 gint
compare_enum_field_class_mappings(struct enum_field_class_mapping
**a
,
406 struct enum_field_class_mapping
**b
)
408 return strcmp((*a
)->label
, (*b
)->label
);
412 gint
compare_enum_field_class_mapping_ranges_signed(
413 struct enum_field_class_mapping_range
*a
,
414 struct enum_field_class_mapping_range
*b
)
417 if (a
->lower
.i
< b
->lower
.i
) {
419 } else if (a
->lower
.i
> b
->lower
.i
) {
422 if (a
->upper
.i
< b
->upper
.i
) {
424 } else if (a
->upper
.i
> b
->upper
.i
) {
433 gint
compare_enum_field_class_mapping_ranges_unsigned(
434 struct enum_field_class_mapping_range
*a
,
435 struct enum_field_class_mapping_range
*b
)
437 if (a
->lower
.u
< b
->lower
.u
) {
439 } else if (a
->lower
.u
> b
->lower
.u
) {
442 if (a
->upper
.u
< b
->upper
.u
) {
444 } else if (a
->upper
.u
> b
->upper
.u
) {
453 void destroy_enum_field_class_mapping(struct enum_field_class_mapping
*mapping
)
455 if (mapping
->ranges
) {
456 g_array_free(mapping
->ranges
, TRUE
);
457 mapping
->ranges
= NULL
;
464 void write_enum_field_class_mapping_range(struct details_write_ctx
*ctx
,
465 struct enum_field_class_mapping_range
*range
, bool is_signed
)
467 g_string_append(ctx
->str
, "[");
470 write_int_prop_value(ctx
, range
->lower
.i
);
472 write_int_prop_value(ctx
, range
->lower
.u
);
475 g_string_append(ctx
->str
, ", ");
478 write_int_prop_value(ctx
, range
->upper
.i
);
480 write_int_prop_value(ctx
, range
->upper
.u
);
483 g_string_append(ctx
->str
, "]");
487 void write_enum_field_class_mappings(struct details_write_ctx
*ctx
,
488 const bt_field_class
*fc
)
493 bool is_signed
= bt_field_class_get_type(fc
) ==
494 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
;
496 mappings
= g_ptr_array_new_with_free_func(
497 (GDestroyNotify
) destroy_enum_field_class_mapping
);
501 * Copy field class's mappings to our own arrays and structures
504 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(fc
); i
++) {
505 const void *fc_mapping
;
506 struct enum_field_class_mapping
*mapping
= g_new0(
507 struct enum_field_class_mapping
, 1);
510 mapping
->ranges
= g_array_new(FALSE
, TRUE
,
511 sizeof(struct enum_field_class_mapping_range
));
512 BT_ASSERT(mapping
->ranges
);
515 fc_mapping
= bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
518 fc_mapping
= bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
522 mapping
->label
= bt_field_class_enumeration_mapping_get_label(
523 bt_field_class_signed_enumeration_mapping_as_mapping_const(
527 range_i
< bt_field_class_enumeration_mapping_get_range_count(
528 bt_field_class_signed_enumeration_mapping_as_mapping_const(fc_mapping
));
530 struct enum_field_class_mapping_range range
;
533 bt_field_class_signed_enumeration_mapping_get_range_by_index(
535 &range
.lower
.i
, &range
.upper
.i
);
537 bt_field_class_unsigned_enumeration_mapping_get_range_by_index(
539 &range
.lower
.u
, &range
.upper
.u
);
542 g_array_append_val(mapping
->ranges
, range
);
545 g_ptr_array_add(mappings
, mapping
);
548 /* Sort mappings, and for each mapping, sort ranges */
549 g_ptr_array_sort(mappings
,
550 (GCompareFunc
) compare_enum_field_class_mappings
);
552 for (i
= 0; i
< mappings
->len
; i
++) {
553 struct enum_field_class_mapping
*mapping
= mappings
->pdata
[i
];
556 g_array_sort(mapping
->ranges
,
558 compare_enum_field_class_mapping_ranges_signed
);
560 g_array_sort(mapping
->ranges
,
562 compare_enum_field_class_mapping_ranges_unsigned
);
567 for (i
= 0; i
< mappings
->len
; i
++) {
568 struct enum_field_class_mapping
*mapping
= mappings
->pdata
[i
];
571 write_compound_member_name(ctx
, mapping
->label
);
573 if (mapping
->ranges
->len
== 1) {
574 /* Single one: write on same line */
576 write_enum_field_class_mapping_range(ctx
,
577 &g_array_index(mapping
->ranges
,
578 struct enum_field_class_mapping_range
,
585 for (range_i
= 0; range_i
< mapping
->ranges
->len
; range_i
++) {
588 write_enum_field_class_mapping_range(ctx
,
589 &g_array_index(mapping
->ranges
,
590 struct enum_field_class_mapping_range
,
591 range_i
), is_signed
);
597 g_ptr_array_free(mappings
, TRUE
);
601 void write_field_path(struct details_write_ctx
*ctx
,
602 const bt_field_path
*field_path
)
606 g_string_append_c(ctx
->str
, '[');
608 switch (bt_field_path_get_root_scope(field_path
)) {
609 case BT_SCOPE_PACKET_CONTEXT
:
610 write_str_prop_value(ctx
, "Packet context");
612 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
613 write_str_prop_value(ctx
, "Event common context");
615 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
616 write_str_prop_value(ctx
, "Event specific context");
618 case BT_SCOPE_EVENT_PAYLOAD
:
619 write_str_prop_value(ctx
, "Event payload");
625 g_string_append(ctx
->str
, ": ");
627 for (i
= 0; i
< bt_field_path_get_item_count(field_path
); i
++) {
628 const bt_field_path_item
*fp_item
=
629 bt_field_path_borrow_item_by_index_const(field_path
, i
);
632 g_string_append(ctx
->str
, ", ");
635 switch (bt_field_path_item_get_type(fp_item
)) {
636 case BT_FIELD_PATH_ITEM_TYPE_INDEX
:
637 write_uint_prop_value(ctx
,
638 bt_field_path_item_index_get_index(fp_item
));
640 case BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
:
641 write_str_prop_value(ctx
, "<current>");
648 g_string_append_c(ctx
->str
, ']');
652 void write_field_class(struct details_write_ctx
*ctx
, const bt_field_class
*fc
,
657 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
659 /* Write field class's name */
661 write_compound_member_name(ctx
, name
);
665 /* Write field class's type */
667 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
668 type
= "Unsigned integer";
670 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
671 type
= "Signed integer";
673 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
674 type
= "Unsigned enumeration";
676 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
677 type
= "Signed enumeration";
679 case BT_FIELD_CLASS_TYPE_REAL
:
682 case BT_FIELD_CLASS_TYPE_STRING
:
685 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
688 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
689 type
= "Static array";
691 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
692 type
= "Dynamic array";
694 case BT_FIELD_CLASS_TYPE_VARIANT
:
701 g_string_append_printf(ctx
->str
, "%s%s%s",
702 color_fg_blue(ctx
), type
, color_reset(ctx
));
704 /* Write field class's properties */
706 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
707 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
709 write_int_field_class_props(ctx
, fc
, true);
711 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
712 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
714 uint64_t mapping_count
=
715 bt_field_class_enumeration_get_mapping_count(fc
);
718 write_int_field_class_props(ctx
, fc
, false);
719 g_string_append(ctx
->str
, ", ");
720 write_uint_prop_value(ctx
, mapping_count
);
721 g_string_append_printf(ctx
->str
, " mapping%s)",
722 plural(mapping_count
));
724 if (mapping_count
> 0) {
725 g_string_append_c(ctx
->str
, ':');
727 write_enum_field_class_mappings(ctx
, fc
);
733 case BT_FIELD_CLASS_TYPE_REAL
:
734 if (bt_field_class_real_is_single_precision(fc
)) {
735 g_string_append(ctx
->str
, " (Single precision)");
737 g_string_append(ctx
->str
, " (Double precision)");
741 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
743 uint64_t member_count
=
744 bt_field_class_structure_get_member_count(fc
);
746 g_string_append(ctx
->str
, " (");
747 write_uint_prop_value(ctx
, member_count
);
748 g_string_append_printf(ctx
->str
, " member%s)",
749 plural(member_count
));
751 if (member_count
> 0) {
752 g_string_append_c(ctx
->str
, ':');
755 for (i
= 0; i
< member_count
; i
++) {
756 const bt_field_class_structure_member
*member
=
757 bt_field_class_structure_borrow_member_by_index_const(
761 write_field_class(ctx
,
762 bt_field_class_structure_member_borrow_field_class_const(member
),
763 bt_field_class_structure_member_get_name(member
));
771 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
772 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
773 if (fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
774 g_string_append(ctx
->str
, " (Length ");
775 write_uint_prop_value(ctx
,
776 bt_field_class_static_array_get_length(fc
));
777 g_string_append_c(ctx
->str
, ')');
779 const bt_field_path
*length_field_path
=
780 bt_field_class_dynamic_array_borrow_length_field_path_const(
783 if (length_field_path
) {
784 g_string_append(ctx
->str
, " (Length field path ");
785 write_field_path(ctx
, length_field_path
);
786 g_string_append_c(ctx
->str
, ')');
790 g_string_append_c(ctx
->str
, ':');
793 write_field_class(ctx
,
794 bt_field_class_array_borrow_element_field_class_const(fc
),
798 case BT_FIELD_CLASS_TYPE_VARIANT
:
800 uint64_t option_count
=
801 bt_field_class_variant_get_option_count(fc
);
802 const bt_field_path
*sel_field_path
=
803 bt_field_class_variant_borrow_selector_field_path_const(
806 g_string_append(ctx
->str
, " (");
807 write_uint_prop_value(ctx
, option_count
);
808 g_string_append_printf(ctx
->str
, " option%s, ",
809 plural(option_count
));
811 if (sel_field_path
) {
812 g_string_append(ctx
->str
, "Selector field path ");
813 write_field_path(ctx
, sel_field_path
);
816 g_string_append_c(ctx
->str
, ')');
818 if (option_count
> 0) {
819 g_string_append_c(ctx
->str
, ':');
822 for (i
= 0; i
< option_count
; i
++) {
823 const bt_field_class_variant_option
*option
=
824 bt_field_class_variant_borrow_option_by_index_const(
828 write_field_class(ctx
,
829 bt_field_class_variant_option_borrow_field_class_const(option
),
830 bt_field_class_variant_option_get_name(option
));
844 void write_root_field_class(struct details_write_ctx
*ctx
, const char *name
,
845 const bt_field_class
*fc
)
850 write_prop_name(ctx
, name
);
851 g_string_append(ctx
->str
, ": ");
852 write_field_class(ctx
, fc
, NULL
);
857 void write_event_class(struct details_write_ctx
*ctx
, const bt_event_class
*ec
)
859 const char *name
= bt_event_class_get_name(ec
);
861 const bt_field_class
*fc
;
862 bt_event_class_log_level log_level
;
865 write_obj_type_name(ctx
, "Event class");
867 /* Write name and ID */
869 g_string_append_printf(ctx
->str
, " `%s%s%s`",
870 color_fg_green(ctx
), name
, color_reset(ctx
));
873 g_string_append(ctx
->str
, " (ID ");
874 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
875 g_string_append(ctx
->str
, "):\n");
877 /* Write properties */
880 /* Write log level */
881 if (bt_event_class_get_log_level(ec
, &log_level
) ==
882 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
883 const char *ll_str
= NULL
;
886 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
887 ll_str
= "Emergency";
889 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
892 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
895 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
898 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
901 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
904 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
907 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
908 ll_str
= "Debug (system)";
910 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
911 ll_str
= "Debug (program)";
913 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
914 ll_str
= "Debug (process)";
916 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
917 ll_str
= "Debug (module)";
919 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
920 ll_str
= "Debug (unit)";
922 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
923 ll_str
= "Debug (function)";
925 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
926 ll_str
= "Debug (line)";
928 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
935 write_str_prop_line(ctx
, "Log level", ll_str
);
939 emf_uri
= bt_event_class_get_emf_uri(ec
);
941 write_str_prop_line(ctx
, "EMF URI", emf_uri
);
944 /* Write specific context field class */
945 fc
= bt_event_class_borrow_specific_context_field_class_const(ec
);
947 write_root_field_class(ctx
, "Specific context field class", fc
);
950 /* Write payload field class */
951 fc
= bt_event_class_borrow_payload_field_class_const(ec
);
953 write_root_field_class(ctx
, "Payload field class", fc
);
960 void write_clock_class_prop_lines(struct details_write_ctx
*ctx
,
961 const bt_clock_class
*cc
)
963 int64_t offset_seconds
;
964 uint64_t offset_cycles
;
967 str
= bt_clock_class_get_name(cc
);
969 write_str_prop_line(ctx
, "Name", str
);
972 str
= bt_clock_class_get_description(cc
);
974 write_str_prop_line(ctx
, "Description", str
);
977 write_uint_prop_line(ctx
, "Frequency (Hz)",
978 bt_clock_class_get_frequency(cc
));
979 write_uint_prop_line(ctx
, "Precision (cycles)",
980 bt_clock_class_get_precision(cc
));
981 bt_clock_class_get_offset(cc
, &offset_seconds
, &offset_cycles
);
982 write_int_prop_line(ctx
, "Offset (s)", offset_seconds
);
983 write_uint_prop_line(ctx
, "Offset (cycles)", offset_cycles
);
984 write_bool_prop_line(ctx
, "Origin is Unix epoch",
985 bt_clock_class_origin_is_unix_epoch(cc
));
987 if (ctx
->details_comp
->cfg
.with_uuid
) {
988 bt_uuid uuid
= bt_clock_class_get_uuid(cc
);
991 write_uuid_prop_line(ctx
, "UUID", uuid
);
997 gint
compare_event_classes(const bt_event_class
**a
, const bt_event_class
**b
)
999 uint64_t id_a
= bt_event_class_get_id(*a
);
1000 uint64_t id_b
= bt_event_class_get_id(*b
);
1004 } else if (id_a
> id_b
) {
1012 void write_stream_class(struct details_write_ctx
*ctx
,
1013 const bt_stream_class
*sc
)
1015 const bt_field_class
*fc
;
1016 GPtrArray
*event_classes
= g_ptr_array_new();
1020 write_obj_type_name(ctx
, "Stream class");
1022 /* Write name and ID */
1023 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
1024 const char *name
= bt_stream_class_get_name(sc
);
1027 g_string_append(ctx
->str
, " `");
1028 write_str_prop_value(ctx
, name
);
1029 g_string_append(ctx
->str
, "`");
1033 g_string_append(ctx
->str
, " (ID ");
1034 write_uint_prop_value(ctx
, bt_stream_class_get_id(sc
));
1035 g_string_append(ctx
->str
, "):\n");
1037 /* Write properties */
1040 /* Write configuration */
1041 write_bool_prop_line(ctx
,
1042 "Packets have beginning default clock snapshot",
1043 bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
));
1044 write_bool_prop_line(ctx
,
1045 "Packets have end default clock snapshot",
1046 bt_stream_class_packets_have_end_default_clock_snapshot(sc
));
1047 write_bool_prop_line(ctx
,
1048 "Supports discarded events",
1049 bt_stream_class_supports_discarded_events(sc
));
1050 write_bool_prop_line(ctx
,
1051 "Discarded events have default clock snapshots",
1052 bt_stream_class_discarded_events_have_default_clock_snapshots(sc
));
1053 write_bool_prop_line(ctx
,
1054 "Supports discarded packets",
1055 bt_stream_class_supports_discarded_packets(sc
));
1056 write_bool_prop_line(ctx
,
1057 "Discarded packets have default clock snapshots",
1058 bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
));
1060 /* Write default clock class */
1061 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
1063 write_prop_name(ctx
, "Default clock class");
1064 g_string_append_c(ctx
->str
, ':');
1067 write_clock_class_prop_lines(ctx
,
1068 bt_stream_class_borrow_default_clock_class_const(sc
));
1072 fc
= bt_stream_class_borrow_packet_context_field_class_const(sc
);
1074 write_root_field_class(ctx
, "Packet context field class", fc
);
1077 fc
= bt_stream_class_borrow_event_common_context_field_class_const(sc
);
1079 write_root_field_class(ctx
, "Event common context field class",
1083 for (i
= 0; i
< bt_stream_class_get_event_class_count(sc
); i
++) {
1084 g_ptr_array_add(event_classes
,
1085 (gpointer
) bt_stream_class_borrow_event_class_by_index_const(
1089 g_ptr_array_sort(event_classes
, (GCompareFunc
) compare_event_classes
);
1091 for (i
= 0; i
< event_classes
->len
; i
++) {
1092 write_event_class(ctx
, event_classes
->pdata
[i
]);
1096 g_ptr_array_free(event_classes
, TRUE
);
1100 gint
compare_stream_classes(const bt_stream_class
**a
, const bt_stream_class
**b
)
1102 uint64_t id_a
= bt_stream_class_get_id(*a
);
1103 uint64_t id_b
= bt_stream_class_get_id(*b
);
1107 } else if (id_a
> id_b
) {
1115 gint
compare_strings(const char **a
, const char **b
)
1117 return strcmp(*a
, *b
);
1121 void write_trace_class(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
)
1123 GPtrArray
*stream_classes
= g_ptr_array_new();
1124 GPtrArray
*env_names
= g_ptr_array_new();
1127 bool printed_prop
= false;
1130 write_obj_type_name(ctx
, "Trace class");
1133 if (ctx
->details_comp
->cfg
.with_trace_class_name
) {
1134 const char *name
= bt_trace_class_get_name(tc
);
1137 g_string_append(ctx
->str
, " `");
1138 write_str_prop_value(ctx
, name
);
1139 g_string_append(ctx
->str
, "`");
1143 /* Write properties */
1146 if (ctx
->details_comp
->cfg
.with_uuid
) {
1147 bt_uuid uuid
= bt_trace_class_get_uuid(tc
);
1150 if (!printed_prop
) {
1151 g_string_append(ctx
->str
, ":\n");
1152 printed_prop
= true;
1155 write_uuid_prop_line(ctx
, "UUID", uuid
);
1159 /* Write environment */
1160 env_count
= bt_trace_class_get_environment_entry_count(tc
);
1161 if (env_count
> 0) {
1162 if (!printed_prop
) {
1163 g_string_append(ctx
->str
, ":\n");
1164 printed_prop
= true;
1168 write_prop_name(ctx
, "Environment");
1169 g_string_append(ctx
->str
, " (");
1170 write_uint_prop_value(ctx
, env_count
);
1171 g_string_append_printf(ctx
->str
, " entr%s):",
1172 env_count
== 1 ? "y" : "ies");
1176 for (i
= 0; i
< env_count
; i
++) {
1178 const bt_value
*value
;
1180 bt_trace_class_borrow_environment_entry_by_index_const(
1181 tc
, i
, &name
, &value
);
1182 g_ptr_array_add(env_names
, (gpointer
) name
);
1185 g_ptr_array_sort(env_names
, (GCompareFunc
) compare_strings
);
1187 for (i
= 0; i
< env_names
->len
; i
++) {
1188 const char *name
= env_names
->pdata
[i
];
1189 const bt_value
*value
=
1190 bt_trace_class_borrow_environment_entry_value_by_name_const(
1194 write_compound_member_name(ctx
, name
);
1197 if (bt_value_get_type(value
) ==
1198 BT_VALUE_TYPE_SIGNED_INTEGER
) {
1199 write_int_prop_value(ctx
,
1200 bt_value_signed_integer_get(value
));
1201 } else if (bt_value_get_type(value
) ==
1202 BT_VALUE_TYPE_STRING
) {
1203 write_str_prop_value(ctx
,
1204 bt_value_string_get(value
));
1215 for (i
= 0; i
< bt_trace_class_get_stream_class_count(tc
); i
++) {
1216 g_ptr_array_add(stream_classes
,
1217 (gpointer
) bt_trace_class_borrow_stream_class_by_index_const(
1221 g_ptr_array_sort(stream_classes
, (GCompareFunc
) compare_stream_classes
);
1223 if (stream_classes
->len
> 0) {
1224 if (!printed_prop
) {
1225 g_string_append(ctx
->str
, ":\n");
1226 printed_prop
= true;
1230 for (i
= 0; i
< stream_classes
->len
; i
++) {
1231 write_stream_class(ctx
, stream_classes
->pdata
[i
]);
1236 if (!printed_prop
) {
1240 g_ptr_array_free(stream_classes
, TRUE
);
1241 g_ptr_array_free(env_names
, TRUE
);
1245 int try_write_meta(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
,
1246 const bt_stream_class
*sc
, const bt_event_class
*ec
)
1252 if (details_need_to_write_trace_class(ctx
, tc
)) {
1255 if (ctx
->details_comp
->cfg
.compact
&&
1256 ctx
->details_comp
->printed_something
) {
1258 * There are no empty line between messages in
1259 * compact mode, so write one here to decouple
1260 * the trace class from the next message.
1266 * write_trace_class() also writes all its stream
1267 * classes their event classes, so we don't need to
1270 write_trace_class(ctx
, tc
);
1274 * Mark this trace class as written, as well as all
1275 * its stream classes and their event classes.
1277 ret
= details_did_write_trace_class(ctx
, tc
);
1282 for (sc_i
= 0; sc_i
< bt_trace_class_get_stream_class_count(tc
);
1285 const bt_stream_class
*tc_sc
=
1286 bt_trace_class_borrow_stream_class_by_index_const(
1289 details_did_write_meta_object(ctx
, tc
, tc_sc
);
1291 for (ec_i
= 0; ec_i
<
1292 bt_stream_class_get_event_class_count(tc_sc
);
1294 details_did_write_meta_object(ctx
, tc
,
1295 bt_stream_class_borrow_event_class_by_index_const(
1303 if (sc
&& details_need_to_write_meta_object(ctx
, tc
, sc
)) {
1308 if (ctx
->details_comp
->cfg
.compact
&&
1309 ctx
->details_comp
->printed_something
) {
1311 * There are no empty line between messages in
1312 * compact mode, so write one here to decouple
1313 * the stream class from the next message.
1319 * write_stream_class() also writes all its event
1320 * classes, so we don't need to rewrite `ec`.
1322 write_stream_class(ctx
, sc
);
1326 * Mark this stream class as written, as well as all its
1329 details_did_write_meta_object(ctx
, tc
, sc
);
1331 for (ec_i
= 0; ec_i
<
1332 bt_stream_class_get_event_class_count(sc
);
1334 details_did_write_meta_object(ctx
, tc
,
1335 bt_stream_class_borrow_event_class_by_index_const(
1342 if (ec
&& details_need_to_write_meta_object(ctx
, tc
, ec
)) {
1345 if (ctx
->details_comp
->cfg
.compact
&&
1346 ctx
->details_comp
->printed_something
) {
1348 * There are no empty line between messages in
1349 * compact mode, so write one here to decouple
1350 * the event class from the next message.
1355 write_event_class(ctx
, ec
);
1357 details_did_write_meta_object(ctx
, tc
, ec
);
1366 void write_time_str(struct details_write_ctx
*ctx
, const char *str
)
1368 if (!ctx
->details_comp
->cfg
.with_time
) {
1372 g_string_append_printf(ctx
->str
, "[%s%s%s%s]",
1373 color_bold(ctx
), color_fg_blue(ctx
), str
, color_reset(ctx
));
1375 if (ctx
->details_comp
->cfg
.compact
) {
1386 void write_time(struct details_write_ctx
*ctx
, const bt_clock_snapshot
*cs
)
1388 bt_clock_snapshot_get_ns_from_origin_status cs_status
;
1389 int64_t ns_from_origin
;
1392 if (!ctx
->details_comp
->cfg
.with_time
) {
1396 format_uint(buf
, bt_clock_snapshot_get_value(cs
), 10);
1397 g_string_append_printf(ctx
->str
, "[%s%s%s%s%s",
1398 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1400 ctx
->details_comp
->cfg
.compact
? "" : " cycles");
1401 cs_status
= bt_clock_snapshot_get_ns_from_origin(cs
, &ns_from_origin
);
1402 if (cs_status
== BT_CLOCK_SNAPSHOT_GET_NS_FROM_ORIGIN_STATUS_OK
) {
1403 format_int(buf
, ns_from_origin
, 10);
1404 g_string_append_printf(ctx
->str
, "%s %s%s%s%s%s",
1405 ctx
->details_comp
->cfg
.compact
? "" : ",",
1406 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1408 ctx
->details_comp
->cfg
.compact
? "" : " ns from origin");
1411 g_string_append(ctx
->str
, "]");
1413 if (ctx
->details_comp
->cfg
.compact
) {
1424 int write_message_follow_tag(struct details_write_ctx
*ctx
,
1425 const bt_stream
*stream
)
1428 uint64_t unique_trace_id
;
1429 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1430 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
1432 ret
= details_trace_unique_id(ctx
, trace
, &unique_trace_id
);
1437 if (ctx
->details_comp
->cfg
.compact
) {
1438 g_string_append_printf(ctx
->str
,
1439 "%s{%s%" PRIu64
" %" PRIu64
" %" PRIu64
"%s%s}%s ",
1440 color_fg_cyan(ctx
), color_bold(ctx
),
1441 unique_trace_id
, bt_stream_class_get_id(sc
),
1442 bt_stream_get_id(stream
),
1443 color_reset(ctx
), color_fg_cyan(ctx
), color_reset(ctx
));
1445 g_string_append_printf(ctx
->str
,
1446 "%s{Trace %s%" PRIu64
"%s%s, Stream class ID %s%" PRIu64
"%s%s, Stream ID %s%" PRIu64
"%s%s}%s\n",
1448 color_bold(ctx
), unique_trace_id
,
1449 color_reset(ctx
), color_fg_cyan(ctx
),
1450 color_bold(ctx
), bt_stream_class_get_id(sc
),
1451 color_reset(ctx
), color_fg_cyan(ctx
),
1452 color_bold(ctx
), bt_stream_get_id(stream
),
1453 color_reset(ctx
), color_fg_cyan(ctx
),
1462 void write_field(struct details_write_ctx
*ctx
, const bt_field
*field
,
1466 bt_field_class_type fc_type
= bt_field_get_class_type(field
);
1467 const bt_field_class
*fc
;
1470 /* Write field's name */
1472 write_compound_member_name(ctx
, name
);
1475 /* Write field's value */
1477 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
1478 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
1479 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
1480 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
1482 unsigned int fmt_base
;
1483 bt_field_class_integer_preferred_display_base base
;
1485 fc
= bt_field_borrow_class_const(field
);
1486 base
= bt_field_class_integer_get_preferred_display_base(fc
);
1489 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
1492 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
1495 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
1498 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
1505 if (fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
1506 fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
1508 bt_field_unsigned_integer_get_value(field
),
1511 write_uint_str_prop_value(ctx
, buf
);
1514 bt_field_signed_integer_get_value(field
),
1517 write_int_str_prop_value(ctx
, buf
);
1522 case BT_FIELD_CLASS_TYPE_REAL
:
1524 write_float_prop_value(ctx
, bt_field_real_get_value(field
));
1526 case BT_FIELD_CLASS_TYPE_STRING
:
1528 write_str_prop_value(ctx
, bt_field_string_get_value(field
));
1530 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1532 uint64_t member_count
;
1534 fc
= bt_field_borrow_class_const(field
);
1535 member_count
= bt_field_class_structure_get_member_count(fc
);
1537 if (member_count
> 0) {
1540 for (i
= 0; i
< member_count
; i
++) {
1541 const bt_field_class_structure_member
*member
=
1542 bt_field_class_structure_borrow_member_by_index_const(
1544 const bt_field
*member_field
=
1545 bt_field_structure_borrow_member_field_by_index_const(
1549 write_field(ctx
, member_field
,
1550 bt_field_class_structure_member_get_name(member
));
1555 g_string_append(ctx
->str
, " Empty");
1560 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1561 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1563 uint64_t length
= bt_field_array_get_length(field
);
1566 g_string_append(ctx
->str
, " Empty");
1568 g_string_append(ctx
->str
, " Length ");
1569 write_uint_prop_value(ctx
, length
);
1570 g_string_append_c(ctx
->str
, ':');
1575 for (i
= 0; i
< length
; i
++) {
1576 const bt_field
*elem_field
=
1577 bt_field_array_borrow_element_field_by_index_const(
1581 write_array_index(ctx
, i
);
1582 write_field(ctx
, elem_field
, NULL
);
1588 case BT_FIELD_CLASS_TYPE_VARIANT
:
1590 bt_field_variant_borrow_selected_option_field_const(
1599 void write_root_field(struct details_write_ctx
*ctx
, const char *name
,
1600 const bt_field
*field
)
1605 write_prop_name(ctx
, name
);
1606 g_string_append(ctx
->str
, ":");
1607 write_field(ctx
, field
, NULL
);
1612 int write_event_message(struct details_write_ctx
*ctx
,
1613 const bt_message
*msg
)
1616 const bt_event
*event
= bt_message_event_borrow_event_const(msg
);
1617 const bt_stream
*stream
= bt_event_borrow_stream_const(event
);
1618 const bt_event_class
*ec
= bt_event_borrow_class_const(event
);
1619 const bt_stream_class
*sc
= bt_event_class_borrow_stream_class_const(ec
);
1620 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
1621 const char *ec_name
;
1622 const bt_field
*field
;
1624 ret
= try_write_meta(ctx
, tc
, sc
, ec
);
1630 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
1632 bt_message_event_borrow_default_clock_snapshot_const(
1636 /* Write follow tag for message */
1637 ret
= write_message_follow_tag(ctx
, stream
);
1642 /* Write object's basic properties */
1643 write_obj_type_name(ctx
, "Event");
1644 ec_name
= bt_event_class_get_name(ec
);
1646 g_string_append_printf(ctx
->str
, " `%s%s%s`",
1647 color_fg_green(ctx
), ec_name
, color_reset(ctx
));
1650 g_string_append(ctx
->str
, " (");
1652 if (!ctx
->details_comp
->cfg
.compact
) {
1653 g_string_append(ctx
->str
, "Class ID ");
1656 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
1657 g_string_append(ctx
->str
, ")");
1659 if (ctx
->details_comp
->cfg
.compact
) {
1665 g_string_append(ctx
->str
, ":\n");
1667 field
= bt_event_borrow_common_context_field_const(event
);
1669 write_root_field(ctx
, "Common context", field
);
1672 field
= bt_event_borrow_specific_context_field_const(event
);
1674 write_root_field(ctx
, "Specific context", field
);
1677 field
= bt_event_borrow_payload_field_const(event
);
1679 write_root_field(ctx
, "Payload", field
);
1690 gint
compare_streams(const bt_stream
**a
, const bt_stream
**b
)
1692 uint64_t id_a
= bt_stream_get_id(*a
);
1693 uint64_t id_b
= bt_stream_get_id(*b
);
1697 } else if (id_a
> id_b
) {
1700 const bt_stream_class
*a_sc
= bt_stream_borrow_class_const(*a
);
1701 const bt_stream_class
*b_sc
= bt_stream_borrow_class_const(*b
);
1702 uint64_t a_sc_id
= bt_stream_class_get_id(a_sc
);
1703 uint64_t b_sc_id
= bt_stream_class_get_id(b_sc
);
1705 if (a_sc_id
< b_sc_id
) {
1707 } else if (a_sc_id
> b_sc_id
) {
1716 void write_trace(struct details_write_ctx
*ctx
, const bt_trace
*trace
)
1719 const bt_trace_class
*tc
= bt_trace_borrow_class_const(trace
);
1720 GPtrArray
*streams
= g_ptr_array_new();
1722 bool printed_prop
= false;
1725 write_obj_type_name(ctx
, "Trace");
1728 if (ctx
->details_comp
->cfg
.with_trace_name
) {
1729 name
= bt_trace_get_name(trace
);
1731 g_string_append(ctx
->str
, " `");
1732 write_str_prop_value(ctx
, name
);
1733 g_string_append(ctx
->str
, "`");
1737 /* Write properties */
1740 if (ctx
->details_comp
->cfg
.with_trace_class_name
) {
1741 name
= bt_trace_class_get_name(tc
);
1743 if (!printed_prop
) {
1744 g_string_append(ctx
->str
, ":\n");
1745 printed_prop
= true;
1748 write_str_prop_line(ctx
, "Class name", name
);
1752 if (ctx
->details_comp
->cfg
.with_uuid
) {
1753 bt_uuid uuid
= bt_trace_class_get_uuid(tc
);
1756 if (!printed_prop
) {
1757 g_string_append(ctx
->str
, ":\n");
1758 printed_prop
= true;
1761 write_uuid_prop_line(ctx
, "Class UUID", uuid
);
1765 for (i
= 0; i
< bt_trace_get_stream_count(trace
); i
++) {
1766 g_ptr_array_add(streams
,
1767 (gpointer
) bt_trace_borrow_stream_by_index_const(
1771 g_ptr_array_sort(streams
, (GCompareFunc
) compare_streams
);
1773 if (streams
->len
> 0 && !printed_prop
) {
1774 g_string_append(ctx
->str
, ":\n");
1775 printed_prop
= true;
1778 for (i
= 0; i
< streams
->len
; i
++) {
1779 const bt_stream
*stream
= streams
->pdata
[i
];
1782 write_obj_type_name(ctx
, "Stream");
1783 g_string_append(ctx
->str
, " (ID ");
1784 write_uint_prop_value(ctx
, bt_stream_get_id(stream
));
1785 g_string_append(ctx
->str
, ", Class ID ");
1786 write_uint_prop_value(ctx
, bt_stream_class_get_id(
1787 bt_stream_borrow_class_const(stream
)));
1788 g_string_append(ctx
->str
, ")");
1794 if (!printed_prop
) {
1798 g_ptr_array_free(streams
, TRUE
);
1802 int write_stream_beginning_message(struct details_write_ctx
*ctx
,
1803 const bt_message
*msg
)
1806 const bt_stream
*stream
=
1807 bt_message_stream_beginning_borrow_stream_const(msg
);
1808 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
1809 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1810 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
1813 ret
= try_write_meta(ctx
, tc
, sc
, NULL
);
1818 /* Write follow tag for message */
1819 ret
= write_message_follow_tag(ctx
, stream
);
1824 /* Write stream properties */
1825 write_obj_type_name(ctx
, "Stream beginning");
1827 if (ctx
->details_comp
->cfg
.compact
) {
1832 g_string_append(ctx
->str
, ":\n");
1835 if (ctx
->details_comp
->cfg
.with_stream_name
) {
1836 name
= bt_stream_get_name(stream
);
1838 write_str_prop_line(ctx
, "Name", name
);
1842 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
1843 name
= bt_stream_class_get_name(sc
);
1845 write_str_prop_line(ctx
, "Class name", name
);
1849 write_trace(ctx
, trace
);
1857 int write_stream_end_message(struct details_write_ctx
*ctx
,
1858 const bt_message
*msg
)
1861 const bt_stream
*stream
=
1862 bt_message_stream_end_borrow_stream_const(msg
);
1864 /* Write follow tag for message */
1865 ret
= write_message_follow_tag(ctx
, stream
);
1870 /* Write stream properties */
1871 write_obj_type_name(ctx
, "Stream end\n");
1878 int write_stream_activity_beginning_message(struct details_write_ctx
*ctx
,
1879 const bt_message
*msg
)
1882 const bt_stream
*stream
=
1883 bt_message_stream_activity_beginning_borrow_stream_const(msg
);
1884 bt_message_stream_activity_clock_snapshot_state cs_state
;
1885 const bt_clock_snapshot
*cs
= NULL
;
1888 cs_state
= bt_message_stream_activity_beginning_borrow_default_clock_snapshot_const(
1891 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN
:
1893 write_time(ctx
, cs
);
1895 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_UNKNOWN
:
1896 write_time_str(ctx
, "Unknown");
1898 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_INFINITE
:
1899 write_time_str(ctx
, "-Infinity");
1905 /* Write follow tag for message */
1906 ret
= write_message_follow_tag(ctx
, stream
);
1911 write_obj_type_name(ctx
, "Stream activity beginning");
1919 int write_stream_activity_end_message(struct details_write_ctx
*ctx
,
1920 const bt_message
*msg
)
1923 const bt_stream
*stream
=
1924 bt_message_stream_activity_end_borrow_stream_const(msg
);
1925 bt_message_stream_activity_clock_snapshot_state cs_state
;
1926 const bt_clock_snapshot
*cs
= NULL
;
1929 cs_state
= bt_message_stream_activity_end_borrow_default_clock_snapshot_const(
1932 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN
:
1934 write_time(ctx
, cs
);
1936 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_UNKNOWN
:
1937 write_time_str(ctx
, "Unknown");
1939 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_INFINITE
:
1940 write_time_str(ctx
, "+Infinity");
1946 /* Write follow tag for message */
1947 ret
= write_message_follow_tag(ctx
, stream
);
1952 write_obj_type_name(ctx
, "Stream activity end");
1960 int write_packet_beginning_message(struct details_write_ctx
*ctx
,
1961 const bt_message
*msg
)
1964 const bt_packet
*packet
=
1965 bt_message_packet_beginning_borrow_packet_const(msg
);
1966 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
1967 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1968 const bt_field
*field
;
1971 if (bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
)) {
1973 bt_message_packet_beginning_borrow_default_clock_snapshot_const(
1977 /* Write follow tag for message */
1978 ret
= write_message_follow_tag(ctx
, stream
);
1983 write_obj_type_name(ctx
, "Packet beginning");
1985 if (ctx
->details_comp
->cfg
.compact
) {
1991 g_string_append(ctx
->str
, ":\n");
1993 field
= bt_packet_borrow_context_field_const(packet
);
1995 write_root_field(ctx
, "Context", field
);
2005 int write_discarded_items_message(struct details_write_ctx
*ctx
,
2006 const char *name
, const bt_stream
*stream
,
2007 const bt_clock_snapshot
*beginning_cs
,
2008 const bt_clock_snapshot
*end_cs
, uint64_t count
)
2014 write_time(ctx
, beginning_cs
);
2016 write_time(ctx
, end_cs
);
2019 /* Write follow tag for message */
2020 ret
= write_message_follow_tag(ctx
, stream
);
2025 write_obj_type_name(ctx
, "Discarded ");
2026 write_obj_type_name(ctx
, name
);
2029 if (count
== UINT64_C(-1)) {
2034 g_string_append(ctx
->str
, " (");
2035 write_uint_prop_value(ctx
, count
);
2036 g_string_append_printf(ctx
->str
, " %s)\n", name
);
2043 int write_discarded_events_message(struct details_write_ctx
*ctx
,
2044 const bt_message
*msg
)
2046 const bt_stream
*stream
= bt_message_discarded_events_borrow_stream_const(
2048 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2049 const bt_clock_snapshot
*beginning_cs
= NULL
;
2050 const bt_clock_snapshot
*end_cs
= NULL
;
2053 if (bt_stream_class_discarded_events_have_default_clock_snapshots(sc
)) {
2055 bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
2058 bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
2062 if (bt_message_discarded_events_get_count(msg
, &count
) !=
2063 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2064 count
= UINT64_C(-1);
2067 return write_discarded_items_message(ctx
, "events", stream
,
2068 beginning_cs
, end_cs
, count
);
2072 int write_discarded_packets_message(struct details_write_ctx
*ctx
,
2073 const bt_message
*msg
)
2075 const bt_stream
*stream
= bt_message_discarded_packets_borrow_stream_const(
2077 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2078 const bt_clock_snapshot
*beginning_cs
= NULL
;
2079 const bt_clock_snapshot
*end_cs
= NULL
;
2082 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
)) {
2084 bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
2087 bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
2091 if (bt_message_discarded_packets_get_count(msg
, &count
) !=
2092 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2093 count
= UINT64_C(-1);
2096 return write_discarded_items_message(ctx
, "packets", stream
,
2097 beginning_cs
, end_cs
, count
);
2101 int write_packet_end_message(struct details_write_ctx
*ctx
,
2102 const bt_message
*msg
)
2105 const bt_packet
*packet
=
2106 bt_message_packet_end_borrow_packet_const(msg
);
2107 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
2108 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2111 if (bt_stream_class_packets_have_end_default_clock_snapshot(sc
)) {
2113 bt_message_packet_end_borrow_default_clock_snapshot_const(
2117 /* Write follow tag for message */
2118 ret
= write_message_follow_tag(ctx
, stream
);
2123 write_obj_type_name(ctx
, "Packet end");
2131 int write_message_iterator_inactivity_message(struct details_write_ctx
*ctx
,
2132 const bt_message
*msg
)
2135 const bt_clock_snapshot
*cs
=
2136 bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const(
2140 write_time(ctx
, cs
);
2141 write_obj_type_name(ctx
, "Message iterator inactivity");
2143 if (ctx
->details_comp
->cfg
.compact
) {
2148 /* Write clock class properties */
2149 g_string_append(ctx
->str
, ":\n");
2152 write_prop_name(ctx
, "Clock class");
2153 g_string_append_c(ctx
->str
, ':');
2156 write_clock_class_prop_lines(ctx
,
2157 bt_clock_snapshot_borrow_clock_class_const(cs
));
2165 int details_write_message(struct details_comp
*details_comp
,
2166 const bt_message
*msg
)
2169 struct details_write_ctx ctx
= {
2170 .details_comp
= details_comp
,
2171 .str
= details_comp
->str
,
2175 /* Reset output buffer */
2176 g_string_assign(details_comp
->str
, "");
2178 if (details_comp
->printed_something
&& !details_comp
->cfg
.compact
) {
2182 switch (bt_message_get_type(msg
)) {
2183 case BT_MESSAGE_TYPE_EVENT
:
2184 ret
= write_event_message(&ctx
, msg
);
2186 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
:
2187 ret
= write_message_iterator_inactivity_message(&ctx
, msg
);
2189 case BT_MESSAGE_TYPE_STREAM_BEGINNING
:
2190 ret
= write_stream_beginning_message(&ctx
, msg
);
2192 case BT_MESSAGE_TYPE_STREAM_END
:
2193 ret
= write_stream_end_message(&ctx
, msg
);
2195 case BT_MESSAGE_TYPE_PACKET_BEGINNING
:
2196 ret
= write_packet_beginning_message(&ctx
, msg
);
2198 case BT_MESSAGE_TYPE_PACKET_END
:
2199 ret
= write_packet_end_message(&ctx
, msg
);
2201 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_BEGINNING
:
2202 ret
= write_stream_activity_beginning_message(&ctx
, msg
);
2204 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_END
:
2205 ret
= write_stream_activity_end_message(&ctx
, msg
);
2207 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
2208 ret
= write_discarded_events_message(&ctx
, msg
);
2210 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
2211 ret
= write_discarded_packets_message(&ctx
, msg
);