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"
29 #include "common/uuid.h"
32 #include "obj-lifetime-mgmt.h"
36 const char *plural(uint64_t value
)
38 return value
== 1 ? "" : "s";
42 void incr_indent_by(struct details_write_ctx
*ctx
, unsigned int value
)
45 ctx
->indent_level
+= value
;
49 void incr_indent(struct details_write_ctx
*ctx
)
51 incr_indent_by(ctx
, 2);
55 void decr_indent_by(struct details_write_ctx
*ctx
, unsigned int value
)
58 BT_ASSERT(ctx
->indent_level
>= value
);
59 ctx
->indent_level
-= value
;
63 void decr_indent(struct details_write_ctx
*ctx
)
65 decr_indent_by(ctx
, 2);
69 void format_uint(char *buf
, uint64_t value
, unsigned int base
)
71 const char *spec
= "%" PRIu64
;
72 char *buf_start
= buf
;
73 unsigned int digits_per_group
= 3;
75 bool sep_digits
= true;
80 /* TODO: Support binary format */
96 * Do not insert digit separators for numbers
97 * under 10,000 as it looks weird.
107 sprintf(buf_start
, spec
, value
);
110 bt_common_sep_digits(buf_start
, digits_per_group
, sep
);
115 void format_int(char *buf
, int64_t value
, unsigned int base
)
117 const char *spec
= "%" PRIu64
;
118 char *buf_start
= buf
;
119 unsigned int digits_per_group
= 3;
121 bool sep_digits
= true;
122 uint64_t abs_value
= value
< 0 ? (uint64_t) -value
: (uint64_t) value
;
132 /* TODO: Support binary format */
134 strcpy(buf_start
, "0x");
136 digits_per_group
= 4;
141 strcpy(buf_start
, "0");
146 if (value
>= -9999 && value
<= 9999) {
148 * Do not insert digit separators for numbers
149 * over -10,000 and under 10,000 as it looks
160 sprintf(buf_start
, spec
, abs_value
);
163 bt_common_sep_digits(buf_start
, digits_per_group
, sep
);
168 void write_nl(struct details_write_ctx
*ctx
)
171 g_string_append_c(ctx
->str
, '\n');
175 void write_sp(struct details_write_ctx
*ctx
)
178 g_string_append_c(ctx
->str
, ' ');
182 void write_indent(struct details_write_ctx
*ctx
)
188 for (i
= 0; i
< ctx
->indent_level
; i
++) {
194 void write_compound_member_name(struct details_write_ctx
*ctx
, const char *name
)
197 g_string_append_printf(ctx
->str
, "%s%s%s:",
198 color_fg_cyan(ctx
), name
, color_reset(ctx
));
202 void write_array_index(struct details_write_ctx
*ctx
, uint64_t index
)
207 format_uint(buf
, index
, 10);
208 g_string_append_printf(ctx
->str
, "%s[%s]%s:",
209 color_fg_cyan(ctx
), buf
, color_reset(ctx
));
213 void write_obj_type_name(struct details_write_ctx
*ctx
, const char *name
)
215 g_string_append_printf(ctx
->str
, "%s%s%s%s",
216 color_fg_yellow(ctx
), color_bold(ctx
), name
, color_reset(ctx
));
220 void write_prop_name(struct details_write_ctx
*ctx
, const char *prop_name
)
222 g_string_append_printf(ctx
->str
, "%s%s%s",
223 color_fg_magenta(ctx
), prop_name
, color_reset(ctx
));
227 void write_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
229 g_string_append_printf(ctx
->str
, "%s%s%s",
230 color_bold(ctx
), value
, color_reset(ctx
));
234 void write_uint_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
236 write_str_prop_value(ctx
, value
);
240 void write_uint_prop_value(struct details_write_ctx
*ctx
, uint64_t value
)
244 format_uint(buf
, value
, 10);
245 write_uint_str_prop_value(ctx
, buf
);
249 void write_int_prop_value(struct details_write_ctx
*ctx
, int64_t value
)
253 format_int(buf
, value
, 10);
254 write_uint_str_prop_value(ctx
, buf
);
258 void write_float_prop_value(struct details_write_ctx
*ctx
, double value
)
260 g_string_append_printf(ctx
->str
, "%s%f%s",
261 color_bold(ctx
), value
, color_reset(ctx
));
265 void write_str_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
266 const char *prop_value
)
268 BT_ASSERT(prop_value
);
270 write_prop_name(ctx
, prop_name
);
271 g_string_append(ctx
->str
, ": ");
272 write_str_prop_value(ctx
, prop_value
);
277 void write_uint_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
281 write_prop_name(ctx
, prop_name
);
282 g_string_append(ctx
->str
, ": ");
283 write_uint_prop_value(ctx
, prop_value
);
288 void write_int_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
292 write_prop_name(ctx
, prop_name
);
293 g_string_append(ctx
->str
, ": ");
294 write_int_prop_value(ctx
, prop_value
);
299 void write_int_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
301 write_str_prop_value(ctx
, value
);
305 void write_bool_prop_value(struct details_write_ctx
*ctx
, bt_bool prop_value
)
309 g_string_append(ctx
->str
, color_bold(ctx
));
312 g_string_append(ctx
->str
, color_fg_green(ctx
));
315 g_string_append(ctx
->str
, color_fg_red(ctx
));
319 g_string_append_printf(ctx
->str
, "%s%s", str
, color_reset(ctx
));
323 void write_bool_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
327 write_prop_name(ctx
, prop_name
);
328 g_string_append(ctx
->str
, ": ");
329 write_bool_prop_value(ctx
, prop_value
);
334 void write_uuid_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
339 write_prop_name(ctx
, prop_name
);
340 g_string_append_printf(ctx
->str
,
341 ": %s" BT_UUID_FMT
"%s\n",
343 BT_UUID_FMT_VALUES(uuid
),
348 void write_int_field_class_props(struct details_write_ctx
*ctx
,
349 const bt_field_class
*fc
, bool close
)
351 g_string_append_printf(ctx
->str
, "(%s%" PRIu64
"-bit%s, Base ",
353 bt_field_class_integer_get_field_value_range(fc
),
356 switch (bt_field_class_integer_get_preferred_display_base(fc
)) {
357 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
358 write_uint_prop_value(ctx
, 2);
360 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
361 write_uint_prop_value(ctx
, 8);
363 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
364 write_uint_prop_value(ctx
, 10);
366 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
367 write_uint_prop_value(ctx
, 16);
374 g_string_append(ctx
->str
, ")");
390 struct enum_field_class_mapping
{
394 /* Array of `struct int_range` */
399 gint
compare_enum_field_class_mappings(struct enum_field_class_mapping
**a
,
400 struct enum_field_class_mapping
**b
)
402 return strcmp((*a
)->label
, (*b
)->label
);
406 gint
compare_int_ranges_signed(struct int_range
*a
, struct int_range
*b
)
409 if (a
->lower
.i
< b
->lower
.i
) {
411 } else if (a
->lower
.i
> b
->lower
.i
) {
414 if (a
->upper
.i
< b
->upper
.i
) {
416 } else if (a
->upper
.i
> b
->upper
.i
) {
425 gint
compare_int_ranges_unsigned(struct int_range
*a
, struct int_range
*b
)
427 if (a
->lower
.u
< b
->lower
.u
) {
429 } else if (a
->lower
.u
> b
->lower
.u
) {
432 if (a
->upper
.u
< b
->upper
.u
) {
434 } else if (a
->upper
.u
> b
->upper
.u
) {
443 GArray
*range_set_to_int_ranges(const void *spec_range_set
, bool is_signed
)
446 const bt_integer_range_set
*range_set
;
447 GArray
*ranges
= g_array_new(FALSE
, TRUE
, sizeof(struct int_range
));
454 range_set
= bt_integer_range_set_signed_as_range_set_const(
457 range_set
= bt_integer_range_set_unsigned_as_range_set_const(
461 for (i
= 0; i
< bt_integer_range_set_get_range_count(range_set
); i
++) {
462 struct int_range range
;
465 const bt_integer_range_signed
*orig_range
=
466 bt_integer_range_set_signed_borrow_range_by_index_const(
469 range
.lower
.i
= bt_integer_range_signed_get_lower(orig_range
);
470 range
.upper
.i
= bt_integer_range_signed_get_upper(orig_range
);
472 const bt_integer_range_unsigned
*orig_range
=
473 bt_integer_range_set_unsigned_borrow_range_by_index_const(
476 range
.lower
.u
= bt_integer_range_unsigned_get_lower(orig_range
);
477 range
.upper
.u
= bt_integer_range_unsigned_get_upper(orig_range
);
480 g_array_append_val(ranges
, range
);
484 g_array_sort(ranges
, (GCompareFunc
) compare_int_ranges_signed
);
487 (GCompareFunc
) compare_int_ranges_unsigned
);
495 void destroy_enum_field_class_mapping(struct enum_field_class_mapping
*mapping
)
497 if (mapping
->ranges
) {
498 g_array_free(mapping
->ranges
, TRUE
);
499 mapping
->ranges
= NULL
;
506 struct int_range
*int_range_at(GArray
*ranges
, uint64_t index
)
508 return &g_array_index(ranges
, struct int_range
, index
);
512 void write_int_range(struct details_write_ctx
*ctx
,
513 struct int_range
*range
, bool is_signed
)
515 g_string_append(ctx
->str
, "[");
518 write_int_prop_value(ctx
, range
->lower
.i
);
520 write_int_prop_value(ctx
, range
->lower
.u
);
523 if (range
->lower
.u
!= range
->upper
.u
) {
524 g_string_append(ctx
->str
, ", ");
527 write_int_prop_value(ctx
, range
->upper
.i
);
529 write_int_prop_value(ctx
, range
->upper
.u
);
533 g_string_append(ctx
->str
, "]");
537 void write_enum_field_class_mappings(struct details_write_ctx
*ctx
,
538 const bt_field_class
*fc
)
543 bool is_signed
= bt_field_class_get_type(fc
) ==
544 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
;
546 mappings
= g_ptr_array_new_with_free_func(
547 (GDestroyNotify
) destroy_enum_field_class_mapping
);
551 * Copy field class's mappings to our own arrays and structures
554 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(fc
); i
++) {
555 const void *fc_mapping
;
556 const void *fc_range_set
;
557 struct enum_field_class_mapping
*mapping
= g_new0(
558 struct enum_field_class_mapping
, 1);
563 fc_mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
565 fc_range_set
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
568 fc_mapping
= bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
570 fc_range_set
= bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
574 mapping
->label
= bt_field_class_enumeration_mapping_get_label(
575 bt_field_class_enumeration_signed_mapping_as_mapping_const(
577 mapping
->ranges
= range_set_to_int_ranges(fc_range_set
,
579 BT_ASSERT(mapping
->ranges
);
580 g_ptr_array_add(mappings
, mapping
);
583 /* Sort mappings (ranges are already sorted within mappings) */
584 g_ptr_array_sort(mappings
,
585 (GCompareFunc
) compare_enum_field_class_mappings
);
588 for (i
= 0; i
< mappings
->len
; i
++) {
589 struct enum_field_class_mapping
*mapping
= mappings
->pdata
[i
];
592 write_compound_member_name(ctx
, mapping
->label
);
594 for (range_i
= 0; range_i
< mapping
->ranges
->len
; range_i
++) {
597 int_range_at(mapping
->ranges
, range_i
),
602 g_ptr_array_free(mappings
, TRUE
);
606 void write_field_path(struct details_write_ctx
*ctx
,
607 const bt_field_path
*field_path
)
611 g_string_append_c(ctx
->str
, '[');
613 switch (bt_field_path_get_root_scope(field_path
)) {
614 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
615 write_str_prop_value(ctx
, "Packet context");
617 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
618 write_str_prop_value(ctx
, "Event common context");
620 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
621 write_str_prop_value(ctx
, "Event specific context");
623 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
624 write_str_prop_value(ctx
, "Event payload");
630 g_string_append(ctx
->str
, ": ");
632 for (i
= 0; i
< bt_field_path_get_item_count(field_path
); i
++) {
633 const bt_field_path_item
*fp_item
=
634 bt_field_path_borrow_item_by_index_const(field_path
, i
);
637 g_string_append(ctx
->str
, ", ");
640 switch (bt_field_path_item_get_type(fp_item
)) {
641 case BT_FIELD_PATH_ITEM_TYPE_INDEX
:
642 write_uint_prop_value(ctx
,
643 bt_field_path_item_index_get_index(fp_item
));
645 case BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
:
646 write_str_prop_value(ctx
, "<current>");
653 g_string_append_c(ctx
->str
, ']');
657 void write_field_class(struct details_write_ctx
*ctx
, const bt_field_class
*fc
);
660 void write_variant_field_class_option(struct details_write_ctx
*ctx
,
661 const bt_field_class
*fc
, uint64_t index
)
663 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
664 const bt_field_class_variant_option
*option
=
665 bt_field_class_variant_borrow_option_by_index_const(
667 const void *orig_ranges
;
668 GArray
*int_ranges
= NULL
;
672 write_compound_member_name(ctx
,
673 bt_field_class_variant_option_get_name(option
));
675 if (fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
) {
676 const bt_field_class_variant_with_selector_unsigned_option
*spec_opt
=
677 bt_field_class_variant_with_selector_unsigned_borrow_option_by_index_const(
681 bt_field_class_variant_with_selector_unsigned_option_borrow_ranges_const(
685 const bt_field_class_variant_with_selector_signed_option
*spec_opt
=
686 bt_field_class_variant_with_selector_signed_borrow_option_by_index_const(
690 bt_field_class_variant_with_selector_signed_option_borrow_ranges_const(
698 int_ranges
= range_set_to_int_ranges(orig_ranges
, is_signed
);
699 BT_ASSERT(int_ranges
);
701 for (i
= 0; i
< int_ranges
->len
; i
++) {
702 struct int_range
*range
= int_range_at(int_ranges
, i
);
705 write_int_range(ctx
, range
, is_signed
);
708 g_string_append(ctx
->str
, ": ");
713 write_field_class(ctx
,
714 bt_field_class_variant_option_borrow_field_class_const(option
));
717 g_array_free(int_ranges
, TRUE
);
722 void write_variant_field_class(struct details_write_ctx
*ctx
,
723 const bt_field_class
*fc
)
725 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
726 uint64_t option_count
=
727 bt_field_class_variant_get_option_count(fc
);
728 const bt_field_path
*sel_field_path
= NULL
;
730 if (fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
) {
732 bt_field_class_variant_with_selector_borrow_selector_field_path_const(
734 BT_ASSERT(sel_field_path
);
737 g_string_append(ctx
->str
, " (");
738 write_uint_prop_value(ctx
, option_count
);
739 g_string_append_printf(ctx
->str
, " option%s, ",
740 plural(option_count
));
742 if (sel_field_path
) {
743 g_string_append(ctx
->str
, "Selector field path ");
744 write_field_path(ctx
, sel_field_path
);
747 g_string_append_c(ctx
->str
, ')');
749 if (option_count
> 0) {
752 g_string_append_c(ctx
->str
, ':');
755 for (i
= 0; i
< option_count
; i
++) {
756 write_variant_field_class_option(ctx
, fc
, i
);
764 void write_field_class(struct details_write_ctx
*ctx
, const bt_field_class
*fc
)
768 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
770 /* Write field class's type */
772 case BT_FIELD_CLASS_TYPE_BOOL
:
775 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
776 type
= "Unsigned integer";
778 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
779 type
= "Signed integer";
781 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
782 type
= "Unsigned enumeration";
784 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
785 type
= "Signed enumeration";
787 case BT_FIELD_CLASS_TYPE_REAL
:
790 case BT_FIELD_CLASS_TYPE_STRING
:
793 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
796 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
797 type
= "Static array";
799 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
800 type
= "Dynamic array";
802 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR
:
803 type
= "Variant (no selector)";
805 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
:
806 type
= "Variant (unsigned selector)";
808 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR
:
809 type
= "Variant (signed selector)";
815 g_string_append_printf(ctx
->str
, "%s%s%s",
816 color_fg_blue(ctx
), type
, color_reset(ctx
));
818 /* Write field class's properties */
820 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
821 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
823 write_int_field_class_props(ctx
, fc
, true);
825 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
826 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
828 uint64_t mapping_count
=
829 bt_field_class_enumeration_get_mapping_count(fc
);
832 write_int_field_class_props(ctx
, fc
, false);
833 g_string_append(ctx
->str
, ", ");
834 write_uint_prop_value(ctx
, mapping_count
);
835 g_string_append_printf(ctx
->str
, " mapping%s)",
836 plural(mapping_count
));
838 if (mapping_count
> 0) {
839 g_string_append_c(ctx
->str
, ':');
841 write_enum_field_class_mappings(ctx
, fc
);
847 case BT_FIELD_CLASS_TYPE_REAL
:
848 if (bt_field_class_real_is_single_precision(fc
)) {
849 g_string_append(ctx
->str
, " (Single precision)");
851 g_string_append(ctx
->str
, " (Double precision)");
855 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
857 uint64_t member_count
=
858 bt_field_class_structure_get_member_count(fc
);
860 g_string_append(ctx
->str
, " (");
861 write_uint_prop_value(ctx
, member_count
);
862 g_string_append_printf(ctx
->str
, " member%s)",
863 plural(member_count
));
865 if (member_count
> 0) {
866 g_string_append_c(ctx
->str
, ':');
869 for (i
= 0; i
< member_count
; i
++) {
870 const bt_field_class_structure_member
*member
=
871 bt_field_class_structure_borrow_member_by_index_const(
875 write_compound_member_name(ctx
,
876 bt_field_class_structure_member_get_name(member
));
878 write_field_class(ctx
,
879 bt_field_class_structure_member_borrow_field_class_const(member
));
887 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
888 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
889 if (fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
890 g_string_append(ctx
->str
, " (Length ");
891 write_uint_prop_value(ctx
,
892 bt_field_class_array_static_get_length(fc
));
893 g_string_append_c(ctx
->str
, ')');
895 const bt_field_path
*length_field_path
=
896 bt_field_class_array_dynamic_borrow_length_field_path_const(
899 if (length_field_path
) {
900 g_string_append(ctx
->str
, " (Length field path ");
901 write_field_path(ctx
, length_field_path
);
902 g_string_append_c(ctx
->str
, ')');
906 g_string_append_c(ctx
->str
, ':');
909 write_compound_member_name(ctx
, "Element");
911 write_field_class(ctx
,
912 bt_field_class_array_borrow_element_field_class_const(fc
));
915 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR
:
916 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
:
917 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR
:
918 write_variant_field_class(ctx
, fc
);
926 void write_root_field_class(struct details_write_ctx
*ctx
, const char *name
,
927 const bt_field_class
*fc
)
932 write_prop_name(ctx
, name
);
933 g_string_append(ctx
->str
, ": ");
934 write_field_class(ctx
, fc
);
939 void write_event_class(struct details_write_ctx
*ctx
, const bt_event_class
*ec
)
941 const char *name
= bt_event_class_get_name(ec
);
943 const bt_field_class
*fc
;
944 bt_event_class_log_level log_level
;
947 write_obj_type_name(ctx
, "Event class");
949 /* Write name and ID */
951 g_string_append_printf(ctx
->str
, " `%s%s%s`",
952 color_fg_green(ctx
), name
, color_reset(ctx
));
955 g_string_append(ctx
->str
, " (ID ");
956 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
957 g_string_append(ctx
->str
, "):\n");
959 /* Write properties */
962 /* Write log level */
963 if (bt_event_class_get_log_level(ec
, &log_level
) ==
964 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
965 const char *ll_str
= NULL
;
968 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
969 ll_str
= "Emergency";
971 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
974 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
977 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
980 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
983 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
986 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
989 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
990 ll_str
= "Debug (system)";
992 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
993 ll_str
= "Debug (program)";
995 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
996 ll_str
= "Debug (process)";
998 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
999 ll_str
= "Debug (module)";
1001 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
1002 ll_str
= "Debug (unit)";
1004 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
1005 ll_str
= "Debug (function)";
1007 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
1008 ll_str
= "Debug (line)";
1010 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
1017 write_str_prop_line(ctx
, "Log level", ll_str
);
1021 emf_uri
= bt_event_class_get_emf_uri(ec
);
1023 write_str_prop_line(ctx
, "EMF URI", emf_uri
);
1026 /* Write specific context field class */
1027 fc
= bt_event_class_borrow_specific_context_field_class_const(ec
);
1029 write_root_field_class(ctx
, "Specific context field class", fc
);
1032 /* Write payload field class */
1033 fc
= bt_event_class_borrow_payload_field_class_const(ec
);
1035 write_root_field_class(ctx
, "Payload field class", fc
);
1042 void write_clock_class_prop_lines(struct details_write_ctx
*ctx
,
1043 const bt_clock_class
*cc
)
1045 int64_t offset_seconds
;
1046 uint64_t offset_cycles
;
1049 str
= bt_clock_class_get_name(cc
);
1051 write_str_prop_line(ctx
, "Name", str
);
1054 str
= bt_clock_class_get_description(cc
);
1056 write_str_prop_line(ctx
, "Description", str
);
1059 write_uint_prop_line(ctx
, "Frequency (Hz)",
1060 bt_clock_class_get_frequency(cc
));
1061 write_uint_prop_line(ctx
, "Precision (cycles)",
1062 bt_clock_class_get_precision(cc
));
1063 bt_clock_class_get_offset(cc
, &offset_seconds
, &offset_cycles
);
1064 write_int_prop_line(ctx
, "Offset (s)", offset_seconds
);
1065 write_uint_prop_line(ctx
, "Offset (cycles)", offset_cycles
);
1066 write_bool_prop_line(ctx
, "Origin is Unix epoch",
1067 bt_clock_class_origin_is_unix_epoch(cc
));
1069 if (ctx
->details_comp
->cfg
.with_uuid
) {
1070 bt_uuid uuid
= bt_clock_class_get_uuid(cc
);
1073 write_uuid_prop_line(ctx
, "UUID", uuid
);
1079 gint
compare_event_classes(const bt_event_class
**a
, const bt_event_class
**b
)
1081 uint64_t id_a
= bt_event_class_get_id(*a
);
1082 uint64_t id_b
= bt_event_class_get_id(*b
);
1086 } else if (id_a
> id_b
) {
1094 void write_stream_class(struct details_write_ctx
*ctx
,
1095 const bt_stream_class
*sc
)
1097 const bt_field_class
*fc
;
1098 GPtrArray
*event_classes
= g_ptr_array_new();
1102 write_obj_type_name(ctx
, "Stream class");
1104 /* Write name and ID */
1105 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
1106 const char *name
= bt_stream_class_get_name(sc
);
1109 g_string_append(ctx
->str
, " `");
1110 write_str_prop_value(ctx
, name
);
1111 g_string_append(ctx
->str
, "`");
1115 g_string_append(ctx
->str
, " (ID ");
1116 write_uint_prop_value(ctx
, bt_stream_class_get_id(sc
));
1117 g_string_append(ctx
->str
, "):\n");
1119 /* Write properties */
1122 /* Write configuration */
1123 write_bool_prop_line(ctx
,
1124 "Supports packets", bt_stream_class_supports_packets(sc
));
1126 if (bt_stream_class_supports_packets(sc
)) {
1127 write_bool_prop_line(ctx
,
1128 "Packets have beginning default clock snapshot",
1129 bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
));
1130 write_bool_prop_line(ctx
,
1131 "Packets have end default clock snapshot",
1132 bt_stream_class_packets_have_end_default_clock_snapshot(sc
));
1135 write_bool_prop_line(ctx
,
1136 "Supports discarded events",
1137 bt_stream_class_supports_discarded_events(sc
));
1139 if (bt_stream_class_supports_discarded_events(sc
)) {
1140 write_bool_prop_line(ctx
,
1141 "Discarded events have default clock snapshots",
1142 bt_stream_class_discarded_events_have_default_clock_snapshots(sc
));
1145 write_bool_prop_line(ctx
,
1146 "Supports discarded packets",
1147 bt_stream_class_supports_discarded_packets(sc
));
1149 if (bt_stream_class_supports_discarded_packets(sc
)) {
1150 write_bool_prop_line(ctx
,
1151 "Discarded packets have default clock snapshots",
1152 bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
));
1155 /* Write default clock class */
1156 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
1158 write_prop_name(ctx
, "Default clock class");
1159 g_string_append_c(ctx
->str
, ':');
1162 write_clock_class_prop_lines(ctx
,
1163 bt_stream_class_borrow_default_clock_class_const(sc
));
1167 fc
= bt_stream_class_borrow_packet_context_field_class_const(sc
);
1169 write_root_field_class(ctx
, "Packet context field class", fc
);
1172 fc
= bt_stream_class_borrow_event_common_context_field_class_const(sc
);
1174 write_root_field_class(ctx
, "Event common context field class",
1178 for (i
= 0; i
< bt_stream_class_get_event_class_count(sc
); i
++) {
1179 g_ptr_array_add(event_classes
,
1180 (gpointer
) bt_stream_class_borrow_event_class_by_index_const(
1184 g_ptr_array_sort(event_classes
, (GCompareFunc
) compare_event_classes
);
1186 for (i
= 0; i
< event_classes
->len
; i
++) {
1187 write_event_class(ctx
, event_classes
->pdata
[i
]);
1191 g_ptr_array_free(event_classes
, TRUE
);
1195 gint
compare_stream_classes(const bt_stream_class
**a
, const bt_stream_class
**b
)
1197 uint64_t id_a
= bt_stream_class_get_id(*a
);
1198 uint64_t id_b
= bt_stream_class_get_id(*b
);
1202 } else if (id_a
> id_b
) {
1210 gint
compare_strings(const char **a
, const char **b
)
1212 return strcmp(*a
, *b
);
1216 void write_trace_class(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
)
1218 GPtrArray
*stream_classes
= g_ptr_array_new();
1220 bool printed_prop
= false;
1223 write_obj_type_name(ctx
, "Trace class");
1225 for (i
= 0; i
< bt_trace_class_get_stream_class_count(tc
); i
++) {
1226 g_ptr_array_add(stream_classes
,
1227 (gpointer
) bt_trace_class_borrow_stream_class_by_index_const(
1231 g_ptr_array_sort(stream_classes
, (GCompareFunc
) compare_stream_classes
);
1233 if (stream_classes
->len
> 0) {
1234 if (!printed_prop
) {
1235 g_string_append(ctx
->str
, ":\n");
1236 printed_prop
= true;
1242 for (i
= 0; i
< stream_classes
->len
; i
++) {
1243 write_stream_class(ctx
, stream_classes
->pdata
[i
]);
1246 if (!printed_prop
) {
1251 g_ptr_array_free(stream_classes
, TRUE
);
1255 int try_write_meta(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
,
1256 const bt_stream_class
*sc
, const bt_event_class
*ec
)
1262 if (details_need_to_write_trace_class(ctx
, tc
)) {
1265 if (ctx
->details_comp
->cfg
.compact
&&
1266 ctx
->details_comp
->printed_something
) {
1268 * There are no empty line between messages in
1269 * compact mode, so write one here to decouple
1270 * the trace class from the next message.
1276 * write_trace_class() also writes all its stream
1277 * classes their event classes, so we don't need to
1280 write_trace_class(ctx
, tc
);
1284 * Mark this trace class as written, as well as all
1285 * its stream classes and their event classes.
1287 ret
= details_did_write_trace_class(ctx
, tc
);
1292 for (sc_i
= 0; sc_i
< bt_trace_class_get_stream_class_count(tc
);
1295 const bt_stream_class
*tc_sc
=
1296 bt_trace_class_borrow_stream_class_by_index_const(
1299 details_did_write_meta_object(ctx
, tc
, tc_sc
);
1301 for (ec_i
= 0; ec_i
<
1302 bt_stream_class_get_event_class_count(tc_sc
);
1304 details_did_write_meta_object(ctx
, tc
,
1305 bt_stream_class_borrow_event_class_by_index_const(
1313 if (sc
&& details_need_to_write_meta_object(ctx
, tc
, sc
)) {
1318 if (ctx
->details_comp
->cfg
.compact
&&
1319 ctx
->details_comp
->printed_something
) {
1321 * There are no empty line between messages in
1322 * compact mode, so write one here to decouple
1323 * the stream class from the next message.
1329 * write_stream_class() also writes all its event
1330 * classes, so we don't need to rewrite `ec`.
1332 write_stream_class(ctx
, sc
);
1336 * Mark this stream class as written, as well as all its
1339 details_did_write_meta_object(ctx
, tc
, sc
);
1341 for (ec_i
= 0; ec_i
<
1342 bt_stream_class_get_event_class_count(sc
);
1344 details_did_write_meta_object(ctx
, tc
,
1345 bt_stream_class_borrow_event_class_by_index_const(
1352 if (ec
&& details_need_to_write_meta_object(ctx
, tc
, ec
)) {
1355 if (ctx
->details_comp
->cfg
.compact
&&
1356 ctx
->details_comp
->printed_something
) {
1358 * There are no empty line between messages in
1359 * compact mode, so write one here to decouple
1360 * the event class from the next message.
1365 write_event_class(ctx
, ec
);
1367 details_did_write_meta_object(ctx
, tc
, ec
);
1376 void write_time_str(struct details_write_ctx
*ctx
, const char *str
)
1378 if (!ctx
->details_comp
->cfg
.with_time
) {
1382 g_string_append_printf(ctx
->str
, "[%s%s%s%s]",
1383 color_bold(ctx
), color_fg_blue(ctx
), str
, color_reset(ctx
));
1385 if (ctx
->details_comp
->cfg
.compact
) {
1396 void write_time(struct details_write_ctx
*ctx
, const bt_clock_snapshot
*cs
)
1398 bt_clock_snapshot_get_ns_from_origin_status cs_status
;
1399 int64_t ns_from_origin
;
1402 if (!ctx
->details_comp
->cfg
.with_time
) {
1406 format_uint(buf
, bt_clock_snapshot_get_value(cs
), 10);
1407 g_string_append_printf(ctx
->str
, "[%s%s%s%s%s",
1408 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1410 ctx
->details_comp
->cfg
.compact
? "" : " cycles");
1411 cs_status
= bt_clock_snapshot_get_ns_from_origin(cs
, &ns_from_origin
);
1412 if (cs_status
== BT_CLOCK_SNAPSHOT_GET_NS_FROM_ORIGIN_STATUS_OK
) {
1413 format_int(buf
, ns_from_origin
, 10);
1414 g_string_append_printf(ctx
->str
, "%s %s%s%s%s%s",
1415 ctx
->details_comp
->cfg
.compact
? "" : ",",
1416 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1418 ctx
->details_comp
->cfg
.compact
? "" : " ns from origin");
1421 g_string_append(ctx
->str
, "]");
1423 if (ctx
->details_comp
->cfg
.compact
) {
1434 int write_message_follow_tag(struct details_write_ctx
*ctx
,
1435 const bt_stream
*stream
)
1438 uint64_t unique_trace_id
;
1439 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1440 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
1442 ret
= details_trace_unique_id(ctx
, trace
, &unique_trace_id
);
1447 if (ctx
->details_comp
->cfg
.compact
) {
1448 g_string_append_printf(ctx
->str
,
1449 "%s{%s%" PRIu64
" %" PRIu64
" %" PRIu64
"%s%s}%s ",
1450 color_fg_cyan(ctx
), color_bold(ctx
),
1451 unique_trace_id
, bt_stream_class_get_id(sc
),
1452 bt_stream_get_id(stream
),
1453 color_reset(ctx
), color_fg_cyan(ctx
), color_reset(ctx
));
1455 g_string_append_printf(ctx
->str
,
1456 "%s{Trace %s%" PRIu64
"%s%s, Stream class ID %s%" PRIu64
"%s%s, Stream ID %s%" PRIu64
"%s%s}%s\n",
1458 color_bold(ctx
), unique_trace_id
,
1459 color_reset(ctx
), color_fg_cyan(ctx
),
1460 color_bold(ctx
), bt_stream_class_get_id(sc
),
1461 color_reset(ctx
), color_fg_cyan(ctx
),
1462 color_bold(ctx
), bt_stream_get_id(stream
),
1463 color_reset(ctx
), color_fg_cyan(ctx
),
1472 void write_field(struct details_write_ctx
*ctx
, const bt_field
*field
,
1476 bt_field_class_type fc_type
= bt_field_get_class_type(field
);
1477 const bt_field_class
*fc
;
1480 /* Write field's name */
1482 write_compound_member_name(ctx
, name
);
1485 /* Write field's value */
1487 case BT_FIELD_CLASS_TYPE_BOOL
:
1489 write_bool_prop_value(ctx
, bt_field_bool_get_value(field
));
1491 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
1492 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
1493 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
1494 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
1496 unsigned int fmt_base
;
1497 bt_field_class_integer_preferred_display_base base
;
1499 fc
= bt_field_borrow_class_const(field
);
1500 base
= bt_field_class_integer_get_preferred_display_base(fc
);
1503 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
1506 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
1509 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
1512 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
1519 if (fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
1520 fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
1522 bt_field_integer_unsigned_get_value(field
),
1525 write_uint_str_prop_value(ctx
, buf
);
1528 bt_field_integer_signed_get_value(field
),
1531 write_int_str_prop_value(ctx
, buf
);
1536 case BT_FIELD_CLASS_TYPE_REAL
:
1538 write_float_prop_value(ctx
, bt_field_real_get_value(field
));
1540 case BT_FIELD_CLASS_TYPE_STRING
:
1542 write_str_prop_value(ctx
, bt_field_string_get_value(field
));
1544 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1546 uint64_t member_count
;
1548 fc
= bt_field_borrow_class_const(field
);
1549 member_count
= bt_field_class_structure_get_member_count(fc
);
1551 if (member_count
> 0) {
1554 for (i
= 0; i
< member_count
; i
++) {
1555 const bt_field_class_structure_member
*member
=
1556 bt_field_class_structure_borrow_member_by_index_const(
1558 const bt_field
*member_field
=
1559 bt_field_structure_borrow_member_field_by_index_const(
1563 write_field(ctx
, member_field
,
1564 bt_field_class_structure_member_get_name(member
));
1569 g_string_append(ctx
->str
, " Empty");
1574 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1575 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1577 uint64_t length
= bt_field_array_get_length(field
);
1580 g_string_append(ctx
->str
, " Empty");
1582 g_string_append(ctx
->str
, " Length ");
1583 write_uint_prop_value(ctx
, length
);
1584 g_string_append_c(ctx
->str
, ':');
1589 for (i
= 0; i
< length
; i
++) {
1590 const bt_field
*elem_field
=
1591 bt_field_array_borrow_element_field_by_index_const(
1595 write_array_index(ctx
, i
);
1596 write_field(ctx
, elem_field
, NULL
);
1602 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR
:
1603 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
:
1604 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR
:
1606 bt_field_variant_borrow_selected_option_field_const(
1615 void write_root_field(struct details_write_ctx
*ctx
, const char *name
,
1616 const bt_field
*field
)
1621 write_prop_name(ctx
, name
);
1622 g_string_append(ctx
->str
, ":");
1623 write_field(ctx
, field
, NULL
);
1628 int write_event_message(struct details_write_ctx
*ctx
,
1629 const bt_message
*msg
)
1632 const bt_event
*event
= bt_message_event_borrow_event_const(msg
);
1633 const bt_stream
*stream
= bt_event_borrow_stream_const(event
);
1634 const bt_event_class
*ec
= bt_event_borrow_class_const(event
);
1635 const bt_stream_class
*sc
= bt_event_class_borrow_stream_class_const(ec
);
1636 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
1637 const char *ec_name
;
1638 const bt_field
*field
;
1640 ret
= try_write_meta(ctx
, tc
, sc
, ec
);
1646 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
1648 bt_message_event_borrow_default_clock_snapshot_const(
1652 /* Write follow tag for message */
1653 ret
= write_message_follow_tag(ctx
, stream
);
1658 /* Write object's basic properties */
1659 write_obj_type_name(ctx
, "Event");
1660 ec_name
= bt_event_class_get_name(ec
);
1662 g_string_append_printf(ctx
->str
, " `%s%s%s`",
1663 color_fg_green(ctx
), ec_name
, color_reset(ctx
));
1666 g_string_append(ctx
->str
, " (");
1668 if (!ctx
->details_comp
->cfg
.compact
) {
1669 g_string_append(ctx
->str
, "Class ID ");
1672 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
1673 g_string_append(ctx
->str
, ")");
1675 if (ctx
->details_comp
->cfg
.compact
) {
1681 g_string_append(ctx
->str
, ":\n");
1683 field
= bt_event_borrow_common_context_field_const(event
);
1685 write_root_field(ctx
, "Common context", field
);
1688 field
= bt_event_borrow_specific_context_field_const(event
);
1690 write_root_field(ctx
, "Specific context", field
);
1693 field
= bt_event_borrow_payload_field_const(event
);
1695 write_root_field(ctx
, "Payload", field
);
1706 gint
compare_streams(const bt_stream
**a
, const bt_stream
**b
)
1708 uint64_t id_a
= bt_stream_get_id(*a
);
1709 uint64_t id_b
= bt_stream_get_id(*b
);
1713 } else if (id_a
> id_b
) {
1716 const bt_stream_class
*a_sc
= bt_stream_borrow_class_const(*a
);
1717 const bt_stream_class
*b_sc
= bt_stream_borrow_class_const(*b
);
1718 uint64_t a_sc_id
= bt_stream_class_get_id(a_sc
);
1719 uint64_t b_sc_id
= bt_stream_class_get_id(b_sc
);
1721 if (a_sc_id
< b_sc_id
) {
1723 } else if (a_sc_id
> b_sc_id
) {
1732 void write_trace(struct details_write_ctx
*ctx
, const bt_trace
*trace
)
1735 GPtrArray
*streams
= g_ptr_array_new();
1737 bool printed_prop
= false;
1738 GPtrArray
*env_names
= g_ptr_array_new();
1742 write_obj_type_name(ctx
, "Trace");
1745 if (ctx
->details_comp
->cfg
.with_trace_name
) {
1746 name
= bt_trace_get_name(trace
);
1748 g_string_append(ctx
->str
, " `");
1749 write_str_prop_value(ctx
, name
);
1750 g_string_append(ctx
->str
, "`");
1754 /* Write properties */
1758 if (ctx
->details_comp
->cfg
.with_uuid
) {
1759 bt_uuid uuid
= bt_trace_get_uuid(trace
);
1762 if (!printed_prop
) {
1763 g_string_append(ctx
->str
, ":\n");
1764 printed_prop
= true;
1767 write_uuid_prop_line(ctx
, "UUID", uuid
);
1771 /* Write environment */
1772 env_count
= bt_trace_get_environment_entry_count(trace
);
1773 if (env_count
> 0) {
1774 if (!printed_prop
) {
1775 g_string_append(ctx
->str
, ":\n");
1776 printed_prop
= true;
1780 write_prop_name(ctx
, "Environment");
1781 g_string_append(ctx
->str
, " (");
1782 write_uint_prop_value(ctx
, env_count
);
1783 g_string_append_printf(ctx
->str
, " entr%s):",
1784 env_count
== 1 ? "y" : "ies");
1788 for (i
= 0; i
< env_count
; i
++) {
1790 const bt_value
*value
;
1792 bt_trace_borrow_environment_entry_by_index_const(
1793 trace
, i
, &name
, &value
);
1794 g_ptr_array_add(env_names
, (gpointer
) name
);
1797 g_ptr_array_sort(env_names
, (GCompareFunc
) compare_strings
);
1799 for (i
= 0; i
< env_names
->len
; i
++) {
1800 const char *name
= env_names
->pdata
[i
];
1801 const bt_value
*value
=
1802 bt_trace_borrow_environment_entry_value_by_name_const(
1806 write_compound_member_name(ctx
, name
);
1809 if (bt_value_get_type(value
) ==
1810 BT_VALUE_TYPE_SIGNED_INTEGER
) {
1811 write_int_prop_value(ctx
,
1812 bt_value_integer_signed_get(value
));
1813 } else if (bt_value_get_type(value
) ==
1814 BT_VALUE_TYPE_STRING
) {
1815 write_str_prop_value(ctx
,
1816 bt_value_string_get(value
));
1827 for (i
= 0; i
< bt_trace_get_stream_count(trace
); i
++) {
1828 g_ptr_array_add(streams
,
1829 (gpointer
) bt_trace_borrow_stream_by_index_const(
1833 g_ptr_array_sort(streams
, (GCompareFunc
) compare_streams
);
1835 if (streams
->len
> 0 && !printed_prop
) {
1836 g_string_append(ctx
->str
, ":\n");
1837 printed_prop
= true;
1840 for (i
= 0; i
< streams
->len
; i
++) {
1841 const bt_stream
*stream
= streams
->pdata
[i
];
1844 write_obj_type_name(ctx
, "Stream");
1845 g_string_append(ctx
->str
, " (ID ");
1846 write_uint_prop_value(ctx
, bt_stream_get_id(stream
));
1847 g_string_append(ctx
->str
, ", Class ID ");
1848 write_uint_prop_value(ctx
, bt_stream_class_get_id(
1849 bt_stream_borrow_class_const(stream
)));
1850 g_string_append(ctx
->str
, ")");
1856 if (!printed_prop
) {
1860 g_ptr_array_free(streams
, TRUE
);
1861 g_ptr_array_free(env_names
, TRUE
);
1865 int write_stream_beginning_message(struct details_write_ctx
*ctx
,
1866 const bt_message
*msg
)
1869 const bt_stream
*stream
=
1870 bt_message_stream_beginning_borrow_stream_const(msg
);
1871 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
1872 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1873 const bt_clock_class
*cc
= bt_stream_class_borrow_default_clock_class_const(sc
);
1874 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
1877 ret
= try_write_meta(ctx
, tc
, sc
, NULL
);
1884 const bt_clock_snapshot
*cs
;
1885 bt_message_stream_clock_snapshot_state cs_state
=
1886 bt_message_stream_beginning_borrow_default_clock_snapshot_const(msg
, &cs
);
1888 if (cs_state
== BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN
) {
1889 write_time(ctx
, cs
);
1891 write_time_str(ctx
, "Unknown");
1895 /* Write follow tag for message */
1896 ret
= write_message_follow_tag(ctx
, stream
);
1901 /* Write stream properties */
1902 write_obj_type_name(ctx
, "Stream beginning");
1904 if (ctx
->details_comp
->cfg
.compact
) {
1909 g_string_append(ctx
->str
, ":\n");
1912 if (ctx
->details_comp
->cfg
.with_stream_name
) {
1913 name
= bt_stream_get_name(stream
);
1915 write_str_prop_line(ctx
, "Name", name
);
1919 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
1920 name
= bt_stream_class_get_name(sc
);
1922 write_str_prop_line(ctx
, "Class name", name
);
1926 write_trace(ctx
, trace
);
1934 int write_stream_end_message(struct details_write_ctx
*ctx
,
1935 const bt_message
*msg
)
1938 const bt_stream
*stream
=
1939 bt_message_stream_end_borrow_stream_const(msg
);
1940 const bt_stream_class
*sc
=
1941 bt_stream_borrow_class_const(stream
);
1942 const bt_clock_class
*cc
=
1943 bt_stream_class_borrow_default_clock_class_const(sc
);
1947 const bt_clock_snapshot
*cs
;
1948 bt_message_stream_clock_snapshot_state cs_state
=
1949 bt_message_stream_end_borrow_default_clock_snapshot_const(msg
, &cs
);
1951 if (cs_state
== BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN
) {
1952 write_time(ctx
, cs
);
1954 write_time_str(ctx
, "Unknown");
1958 /* Write follow tag for message */
1959 ret
= write_message_follow_tag(ctx
, stream
);
1964 /* Write stream properties */
1965 write_obj_type_name(ctx
, "Stream end\n");
1972 int write_packet_beginning_message(struct details_write_ctx
*ctx
,
1973 const bt_message
*msg
)
1976 const bt_packet
*packet
=
1977 bt_message_packet_beginning_borrow_packet_const(msg
);
1978 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
1979 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1980 const bt_field
*field
;
1983 if (bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
)) {
1985 bt_message_packet_beginning_borrow_default_clock_snapshot_const(
1989 /* Write follow tag for message */
1990 ret
= write_message_follow_tag(ctx
, stream
);
1995 write_obj_type_name(ctx
, "Packet beginning");
1997 if (ctx
->details_comp
->cfg
.compact
) {
2003 g_string_append(ctx
->str
, ":\n");
2005 field
= bt_packet_borrow_context_field_const(packet
);
2007 write_root_field(ctx
, "Context", field
);
2017 int write_discarded_items_message(struct details_write_ctx
*ctx
,
2018 const char *name
, const bt_stream
*stream
,
2019 const bt_clock_snapshot
*beginning_cs
,
2020 const bt_clock_snapshot
*end_cs
, uint64_t count
)
2026 write_time(ctx
, beginning_cs
);
2028 write_time(ctx
, end_cs
);
2031 /* Write follow tag for message */
2032 ret
= write_message_follow_tag(ctx
, stream
);
2037 write_obj_type_name(ctx
, "Discarded ");
2038 write_obj_type_name(ctx
, name
);
2041 if (count
== UINT64_C(-1)) {
2046 g_string_append(ctx
->str
, " (");
2047 write_uint_prop_value(ctx
, count
);
2048 g_string_append_printf(ctx
->str
, " %s)\n", name
);
2055 int write_discarded_events_message(struct details_write_ctx
*ctx
,
2056 const bt_message
*msg
)
2058 const bt_stream
*stream
= bt_message_discarded_events_borrow_stream_const(
2060 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2061 const bt_clock_snapshot
*beginning_cs
= NULL
;
2062 const bt_clock_snapshot
*end_cs
= NULL
;
2065 if (bt_stream_class_discarded_events_have_default_clock_snapshots(sc
)) {
2067 bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
2070 bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
2074 if (bt_message_discarded_events_get_count(msg
, &count
) !=
2075 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2076 count
= UINT64_C(-1);
2079 return write_discarded_items_message(ctx
, "events", stream
,
2080 beginning_cs
, end_cs
, count
);
2084 int write_discarded_packets_message(struct details_write_ctx
*ctx
,
2085 const bt_message
*msg
)
2087 const bt_stream
*stream
= bt_message_discarded_packets_borrow_stream_const(
2089 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2090 const bt_clock_snapshot
*beginning_cs
= NULL
;
2091 const bt_clock_snapshot
*end_cs
= NULL
;
2094 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
)) {
2096 bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
2099 bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
2103 if (bt_message_discarded_packets_get_count(msg
, &count
) !=
2104 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2105 count
= UINT64_C(-1);
2108 return write_discarded_items_message(ctx
, "packets", stream
,
2109 beginning_cs
, end_cs
, count
);
2113 int write_packet_end_message(struct details_write_ctx
*ctx
,
2114 const bt_message
*msg
)
2117 const bt_packet
*packet
=
2118 bt_message_packet_end_borrow_packet_const(msg
);
2119 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
2120 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2123 if (bt_stream_class_packets_have_end_default_clock_snapshot(sc
)) {
2125 bt_message_packet_end_borrow_default_clock_snapshot_const(
2129 /* Write follow tag for message */
2130 ret
= write_message_follow_tag(ctx
, stream
);
2135 write_obj_type_name(ctx
, "Packet end");
2143 int write_message_iterator_inactivity_message(struct details_write_ctx
*ctx
,
2144 const bt_message
*msg
)
2147 const bt_clock_snapshot
*cs
=
2148 bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const(
2152 write_time(ctx
, cs
);
2153 write_obj_type_name(ctx
, "Message iterator inactivity");
2155 if (ctx
->details_comp
->cfg
.compact
) {
2160 /* Write clock class properties */
2161 g_string_append(ctx
->str
, ":\n");
2164 write_prop_name(ctx
, "Clock class");
2165 g_string_append_c(ctx
->str
, ':');
2168 write_clock_class_prop_lines(ctx
,
2169 bt_clock_snapshot_borrow_clock_class_const(cs
));
2177 int details_write_message(struct details_comp
*details_comp
,
2178 const bt_message
*msg
)
2181 struct details_write_ctx ctx
= {
2182 .details_comp
= details_comp
,
2183 .str
= details_comp
->str
,
2187 /* Reset output buffer */
2188 g_string_assign(details_comp
->str
, "");
2190 if (details_comp
->printed_something
&& !details_comp
->cfg
.compact
) {
2194 switch (bt_message_get_type(msg
)) {
2195 case BT_MESSAGE_TYPE_EVENT
:
2196 ret
= write_event_message(&ctx
, msg
);
2198 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
:
2199 ret
= write_message_iterator_inactivity_message(&ctx
, msg
);
2201 case BT_MESSAGE_TYPE_STREAM_BEGINNING
:
2202 ret
= write_stream_beginning_message(&ctx
, msg
);
2204 case BT_MESSAGE_TYPE_STREAM_END
:
2205 ret
= write_stream_end_message(&ctx
, msg
);
2207 case BT_MESSAGE_TYPE_PACKET_BEGINNING
:
2208 ret
= write_packet_beginning_message(&ctx
, msg
);
2210 case BT_MESSAGE_TYPE_PACKET_END
:
2211 ret
= write_packet_end_message(&ctx
, msg
);
2213 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
2214 ret
= write_discarded_events_message(&ctx
, msg
);
2216 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
2217 ret
= write_discarded_packets_message(&ctx
, msg
);