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_none_prop_value(struct details_write_ctx
*ctx
, const char *value
)
236 g_string_append_printf(ctx
->str
, "%s%s%s%s",
237 color_bold(ctx
), color_fg_magenta(ctx
),
238 value
, color_reset(ctx
));
242 void write_uint_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
244 write_str_prop_value(ctx
, value
);
248 void write_uint_prop_value(struct details_write_ctx
*ctx
, uint64_t value
)
252 format_uint(buf
, value
, 10);
253 write_uint_str_prop_value(ctx
, buf
);
257 void write_int_prop_value(struct details_write_ctx
*ctx
, int64_t value
)
261 format_int(buf
, value
, 10);
262 write_uint_str_prop_value(ctx
, buf
);
266 void write_float_prop_value(struct details_write_ctx
*ctx
, double value
)
268 g_string_append_printf(ctx
->str
, "%s%f%s",
269 color_bold(ctx
), value
, color_reset(ctx
));
273 void write_str_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
274 const char *prop_value
)
276 BT_ASSERT(prop_value
);
278 write_prop_name(ctx
, prop_name
);
279 g_string_append(ctx
->str
, ": ");
280 write_str_prop_value(ctx
, prop_value
);
285 void write_uint_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
289 write_prop_name(ctx
, prop_name
);
290 g_string_append(ctx
->str
, ": ");
291 write_uint_prop_value(ctx
, prop_value
);
296 void write_int_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
300 write_prop_name(ctx
, prop_name
);
301 g_string_append(ctx
->str
, ": ");
302 write_int_prop_value(ctx
, prop_value
);
307 void write_int_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
309 write_str_prop_value(ctx
, value
);
313 void write_bool_prop_value(struct details_write_ctx
*ctx
, bt_bool prop_value
)
317 g_string_append(ctx
->str
, color_bold(ctx
));
320 g_string_append(ctx
->str
, color_fg_green(ctx
));
323 g_string_append(ctx
->str
, color_fg_red(ctx
));
327 g_string_append_printf(ctx
->str
, "%s%s", str
, color_reset(ctx
));
331 void write_bool_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
335 write_prop_name(ctx
, prop_name
);
336 g_string_append(ctx
->str
, ": ");
337 write_bool_prop_value(ctx
, prop_value
);
342 void write_uuid_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
347 write_prop_name(ctx
, prop_name
);
348 g_string_append_printf(ctx
->str
,
349 ": %s" BT_UUID_FMT
"%s\n",
351 BT_UUID_FMT_VALUES(uuid
),
356 void write_int_field_class_props(struct details_write_ctx
*ctx
,
357 const bt_field_class
*fc
, bool close
)
359 g_string_append_printf(ctx
->str
, "(%s%" PRIu64
"-bit%s, Base ",
361 bt_field_class_integer_get_field_value_range(fc
),
364 switch (bt_field_class_integer_get_preferred_display_base(fc
)) {
365 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
366 write_uint_prop_value(ctx
, 2);
368 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
369 write_uint_prop_value(ctx
, 8);
371 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
372 write_uint_prop_value(ctx
, 10);
374 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
375 write_uint_prop_value(ctx
, 16);
382 g_string_append(ctx
->str
, ")");
398 struct enum_field_class_mapping
{
402 /* Array of `struct int_range` */
407 gint
compare_enum_field_class_mappings(struct enum_field_class_mapping
**a
,
408 struct enum_field_class_mapping
**b
)
410 return strcmp((*a
)->label
, (*b
)->label
);
414 gint
compare_int_ranges_signed(struct int_range
*a
, struct int_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_int_ranges_unsigned(struct int_range
*a
, struct int_range
*b
)
435 if (a
->lower
.u
< b
->lower
.u
) {
437 } else if (a
->lower
.u
> b
->lower
.u
) {
440 if (a
->upper
.u
< b
->upper
.u
) {
442 } else if (a
->upper
.u
> b
->upper
.u
) {
451 GArray
*range_set_to_int_ranges(const void *spec_range_set
, bool is_signed
)
454 const bt_integer_range_set
*range_set
;
455 GArray
*ranges
= g_array_new(FALSE
, TRUE
, sizeof(struct int_range
));
462 range_set
= bt_integer_range_set_signed_as_range_set_const(
465 range_set
= bt_integer_range_set_unsigned_as_range_set_const(
469 for (i
= 0; i
< bt_integer_range_set_get_range_count(range_set
); i
++) {
470 struct int_range range
;
473 const bt_integer_range_signed
*orig_range
=
474 bt_integer_range_set_signed_borrow_range_by_index_const(
477 range
.lower
.i
= bt_integer_range_signed_get_lower(orig_range
);
478 range
.upper
.i
= bt_integer_range_signed_get_upper(orig_range
);
480 const bt_integer_range_unsigned
*orig_range
=
481 bt_integer_range_set_unsigned_borrow_range_by_index_const(
484 range
.lower
.u
= bt_integer_range_unsigned_get_lower(orig_range
);
485 range
.upper
.u
= bt_integer_range_unsigned_get_upper(orig_range
);
488 g_array_append_val(ranges
, range
);
492 g_array_sort(ranges
, (GCompareFunc
) compare_int_ranges_signed
);
495 (GCompareFunc
) compare_int_ranges_unsigned
);
503 void destroy_enum_field_class_mapping(struct enum_field_class_mapping
*mapping
)
505 if (mapping
->ranges
) {
506 g_array_free(mapping
->ranges
, TRUE
);
507 mapping
->ranges
= NULL
;
514 struct int_range
*int_range_at(GArray
*ranges
, uint64_t index
)
516 return &g_array_index(ranges
, struct int_range
, index
);
520 void write_int_range(struct details_write_ctx
*ctx
,
521 struct int_range
*range
, bool is_signed
)
523 g_string_append(ctx
->str
, "[");
526 write_int_prop_value(ctx
, range
->lower
.i
);
528 write_int_prop_value(ctx
, range
->lower
.u
);
531 if (range
->lower
.u
!= range
->upper
.u
) {
532 g_string_append(ctx
->str
, ", ");
535 write_int_prop_value(ctx
, range
->upper
.i
);
537 write_int_prop_value(ctx
, range
->upper
.u
);
541 g_string_append(ctx
->str
, "]");
545 void write_enum_field_class_mappings(struct details_write_ctx
*ctx
,
546 const bt_field_class
*fc
)
551 bool is_signed
= bt_field_class_get_type(fc
) ==
552 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
;
554 mappings
= g_ptr_array_new_with_free_func(
555 (GDestroyNotify
) destroy_enum_field_class_mapping
);
559 * Copy field class's mappings to our own arrays and structures
562 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(fc
); i
++) {
563 const void *fc_mapping
;
564 const void *fc_range_set
;
565 struct enum_field_class_mapping
*mapping
= g_new0(
566 struct enum_field_class_mapping
, 1);
571 fc_mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
573 fc_range_set
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
576 fc_mapping
= bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
578 fc_range_set
= bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
582 mapping
->label
= bt_field_class_enumeration_mapping_get_label(
583 bt_field_class_enumeration_signed_mapping_as_mapping_const(
585 mapping
->ranges
= range_set_to_int_ranges(fc_range_set
,
587 BT_ASSERT(mapping
->ranges
);
588 g_ptr_array_add(mappings
, mapping
);
591 /* Sort mappings (ranges are already sorted within mappings) */
592 g_ptr_array_sort(mappings
,
593 (GCompareFunc
) compare_enum_field_class_mappings
);
596 for (i
= 0; i
< mappings
->len
; i
++) {
597 struct enum_field_class_mapping
*mapping
= mappings
->pdata
[i
];
600 write_compound_member_name(ctx
, mapping
->label
);
602 for (range_i
= 0; range_i
< mapping
->ranges
->len
; range_i
++) {
605 int_range_at(mapping
->ranges
, range_i
),
610 g_ptr_array_free(mappings
, TRUE
);
614 void write_field_path(struct details_write_ctx
*ctx
,
615 const bt_field_path
*field_path
)
619 g_string_append_c(ctx
->str
, '[');
621 switch (bt_field_path_get_root_scope(field_path
)) {
622 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
623 write_str_prop_value(ctx
, "Packet context");
625 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
626 write_str_prop_value(ctx
, "Event common context");
628 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
629 write_str_prop_value(ctx
, "Event specific context");
631 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
632 write_str_prop_value(ctx
, "Event payload");
638 g_string_append(ctx
->str
, ": ");
640 for (i
= 0; i
< bt_field_path_get_item_count(field_path
); i
++) {
641 const bt_field_path_item
*fp_item
=
642 bt_field_path_borrow_item_by_index_const(field_path
, i
);
645 g_string_append(ctx
->str
, ", ");
648 switch (bt_field_path_item_get_type(fp_item
)) {
649 case BT_FIELD_PATH_ITEM_TYPE_INDEX
:
650 write_uint_prop_value(ctx
,
651 bt_field_path_item_index_get_index(fp_item
));
653 case BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
:
654 write_str_prop_value(ctx
, "<current>");
661 g_string_append_c(ctx
->str
, ']');
665 void write_field_class(struct details_write_ctx
*ctx
, const bt_field_class
*fc
);
668 void write_variant_field_class_option(struct details_write_ctx
*ctx
,
669 const bt_field_class
*fc
, uint64_t index
)
671 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
672 const bt_field_class_variant_option
*option
=
673 bt_field_class_variant_borrow_option_by_index_const(
675 const void *orig_ranges
;
676 GArray
*int_ranges
= NULL
;
680 write_compound_member_name(ctx
,
681 bt_field_class_variant_option_get_name(option
));
683 if (fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
) {
684 const bt_field_class_variant_with_selector_unsigned_option
*spec_opt
=
685 bt_field_class_variant_with_selector_unsigned_borrow_option_by_index_const(
689 bt_field_class_variant_with_selector_unsigned_option_borrow_ranges_const(
693 const bt_field_class_variant_with_selector_signed_option
*spec_opt
=
694 bt_field_class_variant_with_selector_signed_borrow_option_by_index_const(
698 bt_field_class_variant_with_selector_signed_option_borrow_ranges_const(
706 int_ranges
= range_set_to_int_ranges(orig_ranges
, is_signed
);
707 BT_ASSERT(int_ranges
);
709 for (i
= 0; i
< int_ranges
->len
; i
++) {
710 struct int_range
*range
= int_range_at(int_ranges
, i
);
713 write_int_range(ctx
, range
, is_signed
);
716 g_string_append(ctx
->str
, ": ");
721 write_field_class(ctx
,
722 bt_field_class_variant_option_borrow_field_class_const(option
));
725 g_array_free(int_ranges
, TRUE
);
730 void write_variant_field_class(struct details_write_ctx
*ctx
,
731 const bt_field_class
*fc
)
733 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
734 uint64_t option_count
=
735 bt_field_class_variant_get_option_count(fc
);
736 const bt_field_path
*sel_field_path
= NULL
;
738 if (fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
) {
740 bt_field_class_variant_with_selector_borrow_selector_field_path_const(
742 BT_ASSERT(sel_field_path
);
745 g_string_append(ctx
->str
, " (");
746 write_uint_prop_value(ctx
, option_count
);
747 g_string_append_printf(ctx
->str
, " option%s, ",
748 plural(option_count
));
750 if (sel_field_path
) {
751 g_string_append(ctx
->str
, "Selector field path ");
752 write_field_path(ctx
, sel_field_path
);
755 g_string_append_c(ctx
->str
, ')');
757 if (option_count
> 0) {
760 g_string_append_c(ctx
->str
, ':');
763 for (i
= 0; i
< option_count
; i
++) {
764 write_variant_field_class_option(ctx
, fc
, i
);
772 void write_field_class(struct details_write_ctx
*ctx
, const bt_field_class
*fc
)
776 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
778 /* Write field class's type */
780 case BT_FIELD_CLASS_TYPE_BOOL
:
783 case BT_FIELD_CLASS_TYPE_BIT_ARRAY
:
786 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
787 type
= "Unsigned integer";
789 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
790 type
= "Signed integer";
792 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
793 type
= "Unsigned enumeration";
795 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
796 type
= "Signed enumeration";
798 case BT_FIELD_CLASS_TYPE_REAL
:
801 case BT_FIELD_CLASS_TYPE_STRING
:
804 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
807 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
808 type
= "Static array";
810 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
811 type
= "Dynamic array";
813 case BT_FIELD_CLASS_TYPE_OPTION
:
816 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR
:
817 type
= "Variant (no selector)";
819 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
:
820 type
= "Variant (unsigned selector)";
822 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR
:
823 type
= "Variant (signed selector)";
829 g_string_append_printf(ctx
->str
, "%s%s%s",
830 color_fg_blue(ctx
), type
, color_reset(ctx
));
832 /* Write field class's properties */
834 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
835 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
837 write_int_field_class_props(ctx
, fc
, true);
839 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
840 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
842 uint64_t mapping_count
=
843 bt_field_class_enumeration_get_mapping_count(fc
);
846 write_int_field_class_props(ctx
, fc
, false);
847 g_string_append(ctx
->str
, ", ");
848 write_uint_prop_value(ctx
, mapping_count
);
849 g_string_append_printf(ctx
->str
, " mapping%s)",
850 plural(mapping_count
));
852 if (mapping_count
> 0) {
853 g_string_append_c(ctx
->str
, ':');
855 write_enum_field_class_mappings(ctx
, fc
);
861 case BT_FIELD_CLASS_TYPE_REAL
:
862 if (bt_field_class_real_is_single_precision(fc
)) {
863 g_string_append(ctx
->str
, " (Single precision)");
865 g_string_append(ctx
->str
, " (Double precision)");
869 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
871 uint64_t member_count
=
872 bt_field_class_structure_get_member_count(fc
);
874 g_string_append(ctx
->str
, " (");
875 write_uint_prop_value(ctx
, member_count
);
876 g_string_append_printf(ctx
->str
, " member%s)",
877 plural(member_count
));
879 if (member_count
> 0) {
880 g_string_append_c(ctx
->str
, ':');
883 for (i
= 0; i
< member_count
; i
++) {
884 const bt_field_class_structure_member
*member
=
885 bt_field_class_structure_borrow_member_by_index_const(
889 write_compound_member_name(ctx
,
890 bt_field_class_structure_member_get_name(member
));
892 write_field_class(ctx
,
893 bt_field_class_structure_member_borrow_field_class_const(member
));
901 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
902 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
903 if (fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
904 g_string_append(ctx
->str
, " (Length ");
905 write_uint_prop_value(ctx
,
906 bt_field_class_array_static_get_length(fc
));
907 g_string_append_c(ctx
->str
, ')');
909 const bt_field_path
*length_field_path
=
910 bt_field_class_array_dynamic_borrow_length_field_path_const(
913 if (length_field_path
) {
914 g_string_append(ctx
->str
, " (Length field path ");
915 write_field_path(ctx
, length_field_path
);
916 g_string_append_c(ctx
->str
, ')');
920 g_string_append_c(ctx
->str
, ':');
923 write_compound_member_name(ctx
, "Element");
925 write_field_class(ctx
,
926 bt_field_class_array_borrow_element_field_class_const(fc
));
929 case BT_FIELD_CLASS_TYPE_OPTION
:
931 const bt_field_path
*selector_field_path
=
932 bt_field_class_option_borrow_selector_field_path_const(fc
);
934 if (selector_field_path
) {
935 g_string_append(ctx
->str
, " (Selector field path ");
936 write_field_path(ctx
, selector_field_path
);
937 g_string_append_c(ctx
->str
, ')');
940 g_string_append_c(ctx
->str
, ':');
943 write_compound_member_name(ctx
, "Content");
945 write_field_class(ctx
,
946 bt_field_class_option_borrow_field_class_const(fc
));
950 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR
:
951 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
:
952 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR
:
953 write_variant_field_class(ctx
, fc
);
961 void write_root_field_class(struct details_write_ctx
*ctx
, const char *name
,
962 const bt_field_class
*fc
)
967 write_prop_name(ctx
, name
);
968 g_string_append(ctx
->str
, ": ");
969 write_field_class(ctx
, fc
);
974 void write_event_class(struct details_write_ctx
*ctx
, const bt_event_class
*ec
)
976 const char *name
= bt_event_class_get_name(ec
);
978 const bt_field_class
*fc
;
979 bt_event_class_log_level log_level
;
982 write_obj_type_name(ctx
, "Event class");
984 /* Write name and ID */
986 g_string_append_printf(ctx
->str
, " `%s%s%s`",
987 color_fg_green(ctx
), name
, color_reset(ctx
));
990 g_string_append(ctx
->str
, " (ID ");
991 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
992 g_string_append(ctx
->str
, "):\n");
994 /* Write properties */
997 /* Write log level */
998 if (bt_event_class_get_log_level(ec
, &log_level
) ==
999 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
1000 const char *ll_str
= NULL
;
1002 switch (log_level
) {
1003 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
1004 ll_str
= "Emergency";
1006 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
1009 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
1010 ll_str
= "Critical";
1012 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
1015 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
1018 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
1021 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
1024 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
1025 ll_str
= "Debug (system)";
1027 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
1028 ll_str
= "Debug (program)";
1030 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
1031 ll_str
= "Debug (process)";
1033 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
1034 ll_str
= "Debug (module)";
1036 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
1037 ll_str
= "Debug (unit)";
1039 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
1040 ll_str
= "Debug (function)";
1042 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
1043 ll_str
= "Debug (line)";
1045 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
1052 write_str_prop_line(ctx
, "Log level", ll_str
);
1056 emf_uri
= bt_event_class_get_emf_uri(ec
);
1058 write_str_prop_line(ctx
, "EMF URI", emf_uri
);
1061 /* Write specific context field class */
1062 fc
= bt_event_class_borrow_specific_context_field_class_const(ec
);
1064 write_root_field_class(ctx
, "Specific context field class", fc
);
1067 /* Write payload field class */
1068 fc
= bt_event_class_borrow_payload_field_class_const(ec
);
1070 write_root_field_class(ctx
, "Payload field class", fc
);
1077 void write_clock_class_prop_lines(struct details_write_ctx
*ctx
,
1078 const bt_clock_class
*cc
)
1080 int64_t offset_seconds
;
1081 uint64_t offset_cycles
;
1084 str
= bt_clock_class_get_name(cc
);
1086 write_str_prop_line(ctx
, "Name", str
);
1089 str
= bt_clock_class_get_description(cc
);
1091 write_str_prop_line(ctx
, "Description", str
);
1094 write_uint_prop_line(ctx
, "Frequency (Hz)",
1095 bt_clock_class_get_frequency(cc
));
1096 write_uint_prop_line(ctx
, "Precision (cycles)",
1097 bt_clock_class_get_precision(cc
));
1098 bt_clock_class_get_offset(cc
, &offset_seconds
, &offset_cycles
);
1099 write_int_prop_line(ctx
, "Offset (s)", offset_seconds
);
1100 write_uint_prop_line(ctx
, "Offset (cycles)", offset_cycles
);
1101 write_bool_prop_line(ctx
, "Origin is Unix epoch",
1102 bt_clock_class_origin_is_unix_epoch(cc
));
1104 if (ctx
->details_comp
->cfg
.with_uuid
) {
1105 bt_uuid uuid
= bt_clock_class_get_uuid(cc
);
1108 write_uuid_prop_line(ctx
, "UUID", uuid
);
1114 gint
compare_event_classes(const bt_event_class
**a
, const bt_event_class
**b
)
1116 uint64_t id_a
= bt_event_class_get_id(*a
);
1117 uint64_t id_b
= bt_event_class_get_id(*b
);
1121 } else if (id_a
> id_b
) {
1129 void write_stream_class(struct details_write_ctx
*ctx
,
1130 const bt_stream_class
*sc
)
1132 const bt_field_class
*fc
;
1133 GPtrArray
*event_classes
= g_ptr_array_new();
1137 write_obj_type_name(ctx
, "Stream class");
1139 /* Write name and ID */
1140 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
1141 const char *name
= bt_stream_class_get_name(sc
);
1144 g_string_append(ctx
->str
, " `");
1145 write_str_prop_value(ctx
, name
);
1146 g_string_append(ctx
->str
, "`");
1150 g_string_append(ctx
->str
, " (ID ");
1151 write_uint_prop_value(ctx
, bt_stream_class_get_id(sc
));
1152 g_string_append(ctx
->str
, "):\n");
1154 /* Write properties */
1157 /* Write configuration */
1158 write_bool_prop_line(ctx
,
1159 "Supports packets", bt_stream_class_supports_packets(sc
));
1161 if (bt_stream_class_supports_packets(sc
)) {
1162 write_bool_prop_line(ctx
,
1163 "Packets have beginning default clock snapshot",
1164 bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
));
1165 write_bool_prop_line(ctx
,
1166 "Packets have end default clock snapshot",
1167 bt_stream_class_packets_have_end_default_clock_snapshot(sc
));
1170 write_bool_prop_line(ctx
,
1171 "Supports discarded events",
1172 bt_stream_class_supports_discarded_events(sc
));
1174 if (bt_stream_class_supports_discarded_events(sc
)) {
1175 write_bool_prop_line(ctx
,
1176 "Discarded events have default clock snapshots",
1177 bt_stream_class_discarded_events_have_default_clock_snapshots(sc
));
1180 write_bool_prop_line(ctx
,
1181 "Supports discarded packets",
1182 bt_stream_class_supports_discarded_packets(sc
));
1184 if (bt_stream_class_supports_discarded_packets(sc
)) {
1185 write_bool_prop_line(ctx
,
1186 "Discarded packets have default clock snapshots",
1187 bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
));
1190 /* Write default clock class */
1191 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
1193 write_prop_name(ctx
, "Default clock class");
1194 g_string_append_c(ctx
->str
, ':');
1197 write_clock_class_prop_lines(ctx
,
1198 bt_stream_class_borrow_default_clock_class_const(sc
));
1202 fc
= bt_stream_class_borrow_packet_context_field_class_const(sc
);
1204 write_root_field_class(ctx
, "Packet context field class", fc
);
1207 fc
= bt_stream_class_borrow_event_common_context_field_class_const(sc
);
1209 write_root_field_class(ctx
, "Event common context field class",
1213 for (i
= 0; i
< bt_stream_class_get_event_class_count(sc
); i
++) {
1214 g_ptr_array_add(event_classes
,
1215 (gpointer
) bt_stream_class_borrow_event_class_by_index_const(
1219 g_ptr_array_sort(event_classes
, (GCompareFunc
) compare_event_classes
);
1221 for (i
= 0; i
< event_classes
->len
; i
++) {
1222 write_event_class(ctx
, event_classes
->pdata
[i
]);
1226 g_ptr_array_free(event_classes
, TRUE
);
1230 gint
compare_stream_classes(const bt_stream_class
**a
, const bt_stream_class
**b
)
1232 uint64_t id_a
= bt_stream_class_get_id(*a
);
1233 uint64_t id_b
= bt_stream_class_get_id(*b
);
1237 } else if (id_a
> id_b
) {
1245 gint
compare_strings(const char **a
, const char **b
)
1247 return strcmp(*a
, *b
);
1251 void write_trace_class(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
)
1253 GPtrArray
*stream_classes
= g_ptr_array_new();
1255 bool printed_prop
= false;
1258 write_obj_type_name(ctx
, "Trace class");
1260 for (i
= 0; i
< bt_trace_class_get_stream_class_count(tc
); i
++) {
1261 g_ptr_array_add(stream_classes
,
1262 (gpointer
) bt_trace_class_borrow_stream_class_by_index_const(
1266 g_ptr_array_sort(stream_classes
, (GCompareFunc
) compare_stream_classes
);
1268 if (stream_classes
->len
> 0) {
1269 if (!printed_prop
) {
1270 g_string_append(ctx
->str
, ":\n");
1271 printed_prop
= true;
1277 for (i
= 0; i
< stream_classes
->len
; i
++) {
1278 write_stream_class(ctx
, stream_classes
->pdata
[i
]);
1281 if (!printed_prop
) {
1286 g_ptr_array_free(stream_classes
, TRUE
);
1290 int try_write_meta(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
,
1291 const bt_stream_class
*sc
, const bt_event_class
*ec
)
1297 if (details_need_to_write_trace_class(ctx
, tc
)) {
1300 if (ctx
->details_comp
->cfg
.compact
&&
1301 ctx
->details_comp
->printed_something
) {
1303 * There are no empty line between messages in
1304 * compact mode, so write one here to decouple
1305 * the trace class from the next message.
1311 * write_trace_class() also writes all its stream
1312 * classes their event classes, so we don't need to
1315 write_trace_class(ctx
, tc
);
1319 * Mark this trace class as written, as well as all
1320 * its stream classes and their event classes.
1322 ret
= details_did_write_trace_class(ctx
, tc
);
1327 for (sc_i
= 0; sc_i
< bt_trace_class_get_stream_class_count(tc
);
1330 const bt_stream_class
*tc_sc
=
1331 bt_trace_class_borrow_stream_class_by_index_const(
1334 details_did_write_meta_object(ctx
, tc
, tc_sc
);
1336 for (ec_i
= 0; ec_i
<
1337 bt_stream_class_get_event_class_count(tc_sc
);
1339 details_did_write_meta_object(ctx
, tc
,
1340 bt_stream_class_borrow_event_class_by_index_const(
1348 if (sc
&& details_need_to_write_meta_object(ctx
, tc
, sc
)) {
1353 if (ctx
->details_comp
->cfg
.compact
&&
1354 ctx
->details_comp
->printed_something
) {
1356 * There are no empty line between messages in
1357 * compact mode, so write one here to decouple
1358 * the stream class from the next message.
1364 * write_stream_class() also writes all its event
1365 * classes, so we don't need to rewrite `ec`.
1367 write_stream_class(ctx
, sc
);
1371 * Mark this stream class as written, as well as all its
1374 details_did_write_meta_object(ctx
, tc
, sc
);
1376 for (ec_i
= 0; ec_i
<
1377 bt_stream_class_get_event_class_count(sc
);
1379 details_did_write_meta_object(ctx
, tc
,
1380 bt_stream_class_borrow_event_class_by_index_const(
1387 if (ec
&& details_need_to_write_meta_object(ctx
, tc
, ec
)) {
1390 if (ctx
->details_comp
->cfg
.compact
&&
1391 ctx
->details_comp
->printed_something
) {
1393 * There are no empty line between messages in
1394 * compact mode, so write one here to decouple
1395 * the event class from the next message.
1400 write_event_class(ctx
, ec
);
1402 details_did_write_meta_object(ctx
, tc
, ec
);
1411 void write_time_str(struct details_write_ctx
*ctx
, const char *str
)
1413 if (!ctx
->details_comp
->cfg
.with_time
) {
1417 g_string_append_printf(ctx
->str
, "[%s%s%s%s]",
1418 color_bold(ctx
), color_fg_blue(ctx
), str
, color_reset(ctx
));
1420 if (ctx
->details_comp
->cfg
.compact
) {
1431 void write_time(struct details_write_ctx
*ctx
, const bt_clock_snapshot
*cs
)
1433 bt_clock_snapshot_get_ns_from_origin_status cs_status
;
1434 int64_t ns_from_origin
;
1437 if (!ctx
->details_comp
->cfg
.with_time
) {
1441 format_uint(buf
, bt_clock_snapshot_get_value(cs
), 10);
1442 g_string_append_printf(ctx
->str
, "[%s%s%s%s%s",
1443 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1445 ctx
->details_comp
->cfg
.compact
? "" : " cycles");
1446 cs_status
= bt_clock_snapshot_get_ns_from_origin(cs
, &ns_from_origin
);
1447 if (cs_status
== BT_CLOCK_SNAPSHOT_GET_NS_FROM_ORIGIN_STATUS_OK
) {
1448 format_int(buf
, ns_from_origin
, 10);
1449 g_string_append_printf(ctx
->str
, "%s %s%s%s%s%s",
1450 ctx
->details_comp
->cfg
.compact
? "" : ",",
1451 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1453 ctx
->details_comp
->cfg
.compact
? "" : " ns from origin");
1456 g_string_append(ctx
->str
, "]");
1458 if (ctx
->details_comp
->cfg
.compact
) {
1469 int write_message_follow_tag(struct details_write_ctx
*ctx
,
1470 const bt_stream
*stream
)
1473 uint64_t unique_trace_id
;
1474 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1475 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
1477 ret
= details_trace_unique_id(ctx
, trace
, &unique_trace_id
);
1482 if (ctx
->details_comp
->cfg
.compact
) {
1483 g_string_append_printf(ctx
->str
,
1484 "%s{%s%" PRIu64
" %" PRIu64
" %" PRIu64
"%s%s}%s ",
1485 color_fg_cyan(ctx
), color_bold(ctx
),
1486 unique_trace_id
, bt_stream_class_get_id(sc
),
1487 bt_stream_get_id(stream
),
1488 color_reset(ctx
), color_fg_cyan(ctx
), color_reset(ctx
));
1490 g_string_append_printf(ctx
->str
,
1491 "%s{Trace %s%" PRIu64
"%s%s, Stream class ID %s%" PRIu64
"%s%s, Stream ID %s%" PRIu64
"%s%s}%s\n",
1493 color_bold(ctx
), unique_trace_id
,
1494 color_reset(ctx
), color_fg_cyan(ctx
),
1495 color_bold(ctx
), bt_stream_class_get_id(sc
),
1496 color_reset(ctx
), color_fg_cyan(ctx
),
1497 color_bold(ctx
), bt_stream_get_id(stream
),
1498 color_reset(ctx
), color_fg_cyan(ctx
),
1507 void write_field(struct details_write_ctx
*ctx
, const bt_field
*field
,
1511 bt_field_class_type fc_type
= bt_field_get_class_type(field
);
1512 const bt_field_class
*fc
;
1515 /* Write field's name */
1517 write_compound_member_name(ctx
, name
);
1520 /* Write field's value */
1522 case BT_FIELD_CLASS_TYPE_BOOL
:
1524 write_bool_prop_value(ctx
, bt_field_bool_get_value(field
));
1526 case BT_FIELD_CLASS_TYPE_BIT_ARRAY
:
1527 format_uint(buf
, bt_field_bit_array_get_value_as_integer(field
),
1530 write_uint_str_prop_value(ctx
, buf
);
1532 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
1533 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
1534 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
1535 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
1537 unsigned int fmt_base
;
1538 bt_field_class_integer_preferred_display_base base
;
1540 fc
= bt_field_borrow_class_const(field
);
1541 base
= bt_field_class_integer_get_preferred_display_base(fc
);
1544 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
1547 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
1550 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
1553 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
1560 if (fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
1561 fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
1563 bt_field_integer_unsigned_get_value(field
),
1566 write_uint_str_prop_value(ctx
, buf
);
1569 bt_field_integer_signed_get_value(field
),
1572 write_int_str_prop_value(ctx
, buf
);
1577 case BT_FIELD_CLASS_TYPE_REAL
:
1579 write_float_prop_value(ctx
, bt_field_real_get_value(field
));
1581 case BT_FIELD_CLASS_TYPE_STRING
:
1583 write_str_prop_value(ctx
, bt_field_string_get_value(field
));
1585 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1587 uint64_t member_count
;
1589 fc
= bt_field_borrow_class_const(field
);
1590 member_count
= bt_field_class_structure_get_member_count(fc
);
1592 if (member_count
> 0) {
1595 for (i
= 0; i
< member_count
; i
++) {
1596 const bt_field_class_structure_member
*member
=
1597 bt_field_class_structure_borrow_member_by_index_const(
1599 const bt_field
*member_field
=
1600 bt_field_structure_borrow_member_field_by_index_const(
1604 write_field(ctx
, member_field
,
1605 bt_field_class_structure_member_get_name(member
));
1611 write_none_prop_value(ctx
, "Empty");
1616 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1617 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1619 uint64_t length
= bt_field_array_get_length(field
);
1623 write_none_prop_value(ctx
, "Empty");
1625 g_string_append(ctx
->str
, " Length ");
1626 write_uint_prop_value(ctx
, length
);
1627 g_string_append_c(ctx
->str
, ':');
1632 for (i
= 0; i
< length
; i
++) {
1633 const bt_field
*elem_field
=
1634 bt_field_array_borrow_element_field_by_index_const(
1638 write_array_index(ctx
, i
);
1639 write_field(ctx
, elem_field
, NULL
);
1645 case BT_FIELD_CLASS_TYPE_OPTION
:
1647 const bt_field
*content_field
=
1648 bt_field_option_borrow_field_const(field
);
1650 if (!content_field
) {
1652 write_none_prop_value(ctx
, "None");
1654 write_field(ctx
, content_field
, NULL
);
1659 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR
:
1660 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
:
1661 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR
:
1663 bt_field_variant_borrow_selected_option_field_const(
1672 void write_root_field(struct details_write_ctx
*ctx
, const char *name
,
1673 const bt_field
*field
)
1678 write_prop_name(ctx
, name
);
1679 g_string_append(ctx
->str
, ":");
1680 write_field(ctx
, field
, NULL
);
1685 int write_event_message(struct details_write_ctx
*ctx
,
1686 const bt_message
*msg
)
1689 const bt_event
*event
= bt_message_event_borrow_event_const(msg
);
1690 const bt_stream
*stream
= bt_event_borrow_stream_const(event
);
1691 const bt_event_class
*ec
= bt_event_borrow_class_const(event
);
1692 const bt_stream_class
*sc
= bt_event_class_borrow_stream_class_const(ec
);
1693 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
1694 const char *ec_name
;
1695 const bt_field
*field
;
1697 ret
= try_write_meta(ctx
, tc
, sc
, ec
);
1703 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
1705 bt_message_event_borrow_default_clock_snapshot_const(
1709 /* Write follow tag for message */
1710 ret
= write_message_follow_tag(ctx
, stream
);
1715 /* Write object's basic properties */
1716 write_obj_type_name(ctx
, "Event");
1717 ec_name
= bt_event_class_get_name(ec
);
1719 g_string_append_printf(ctx
->str
, " `%s%s%s`",
1720 color_fg_green(ctx
), ec_name
, color_reset(ctx
));
1723 g_string_append(ctx
->str
, " (");
1725 if (!ctx
->details_comp
->cfg
.compact
) {
1726 g_string_append(ctx
->str
, "Class ID ");
1729 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
1730 g_string_append(ctx
->str
, ")");
1732 if (ctx
->details_comp
->cfg
.compact
) {
1738 g_string_append(ctx
->str
, ":\n");
1740 field
= bt_event_borrow_common_context_field_const(event
);
1742 write_root_field(ctx
, "Common context", field
);
1745 field
= bt_event_borrow_specific_context_field_const(event
);
1747 write_root_field(ctx
, "Specific context", field
);
1750 field
= bt_event_borrow_payload_field_const(event
);
1752 write_root_field(ctx
, "Payload", field
);
1763 gint
compare_streams(const bt_stream
**a
, const bt_stream
**b
)
1765 uint64_t id_a
= bt_stream_get_id(*a
);
1766 uint64_t id_b
= bt_stream_get_id(*b
);
1770 } else if (id_a
> id_b
) {
1773 const bt_stream_class
*a_sc
= bt_stream_borrow_class_const(*a
);
1774 const bt_stream_class
*b_sc
= bt_stream_borrow_class_const(*b
);
1775 uint64_t a_sc_id
= bt_stream_class_get_id(a_sc
);
1776 uint64_t b_sc_id
= bt_stream_class_get_id(b_sc
);
1778 if (a_sc_id
< b_sc_id
) {
1780 } else if (a_sc_id
> b_sc_id
) {
1789 void write_trace(struct details_write_ctx
*ctx
, const bt_trace
*trace
)
1792 GPtrArray
*streams
= g_ptr_array_new();
1794 bool printed_prop
= false;
1795 GPtrArray
*env_names
= g_ptr_array_new();
1799 write_obj_type_name(ctx
, "Trace");
1802 if (ctx
->details_comp
->cfg
.with_trace_name
) {
1803 name
= bt_trace_get_name(trace
);
1805 g_string_append(ctx
->str
, " `");
1806 write_str_prop_value(ctx
, name
);
1807 g_string_append(ctx
->str
, "`");
1811 /* Write properties */
1815 if (ctx
->details_comp
->cfg
.with_uuid
) {
1816 bt_uuid uuid
= bt_trace_get_uuid(trace
);
1819 if (!printed_prop
) {
1820 g_string_append(ctx
->str
, ":\n");
1821 printed_prop
= true;
1824 write_uuid_prop_line(ctx
, "UUID", uuid
);
1828 /* Write environment */
1829 env_count
= bt_trace_get_environment_entry_count(trace
);
1830 if (env_count
> 0) {
1831 if (!printed_prop
) {
1832 g_string_append(ctx
->str
, ":\n");
1833 printed_prop
= true;
1837 write_prop_name(ctx
, "Environment");
1838 g_string_append(ctx
->str
, " (");
1839 write_uint_prop_value(ctx
, env_count
);
1840 g_string_append_printf(ctx
->str
, " entr%s):",
1841 env_count
== 1 ? "y" : "ies");
1845 for (i
= 0; i
< env_count
; i
++) {
1847 const bt_value
*value
;
1849 bt_trace_borrow_environment_entry_by_index_const(
1850 trace
, i
, &name
, &value
);
1851 g_ptr_array_add(env_names
, (gpointer
) name
);
1854 g_ptr_array_sort(env_names
, (GCompareFunc
) compare_strings
);
1856 for (i
= 0; i
< env_names
->len
; i
++) {
1857 const char *name
= env_names
->pdata
[i
];
1858 const bt_value
*value
=
1859 bt_trace_borrow_environment_entry_value_by_name_const(
1863 write_compound_member_name(ctx
, name
);
1866 if (bt_value_get_type(value
) ==
1867 BT_VALUE_TYPE_SIGNED_INTEGER
) {
1868 write_int_prop_value(ctx
,
1869 bt_value_integer_signed_get(value
));
1870 } else if (bt_value_get_type(value
) ==
1871 BT_VALUE_TYPE_STRING
) {
1872 write_str_prop_value(ctx
,
1873 bt_value_string_get(value
));
1884 for (i
= 0; i
< bt_trace_get_stream_count(trace
); i
++) {
1885 g_ptr_array_add(streams
,
1886 (gpointer
) bt_trace_borrow_stream_by_index_const(
1890 g_ptr_array_sort(streams
, (GCompareFunc
) compare_streams
);
1892 if (streams
->len
> 0 && !printed_prop
) {
1893 g_string_append(ctx
->str
, ":\n");
1894 printed_prop
= true;
1897 for (i
= 0; i
< streams
->len
; i
++) {
1898 const bt_stream
*stream
= streams
->pdata
[i
];
1901 write_obj_type_name(ctx
, "Stream");
1902 g_string_append(ctx
->str
, " (ID ");
1903 write_uint_prop_value(ctx
, bt_stream_get_id(stream
));
1904 g_string_append(ctx
->str
, ", Class ID ");
1905 write_uint_prop_value(ctx
, bt_stream_class_get_id(
1906 bt_stream_borrow_class_const(stream
)));
1907 g_string_append(ctx
->str
, ")");
1913 if (!printed_prop
) {
1917 g_ptr_array_free(streams
, TRUE
);
1918 g_ptr_array_free(env_names
, TRUE
);
1922 int write_stream_beginning_message(struct details_write_ctx
*ctx
,
1923 const bt_message
*msg
)
1926 const bt_stream
*stream
=
1927 bt_message_stream_beginning_borrow_stream_const(msg
);
1928 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
1929 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1930 const bt_clock_class
*cc
= bt_stream_class_borrow_default_clock_class_const(sc
);
1931 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
1934 ret
= try_write_meta(ctx
, tc
, sc
, NULL
);
1941 const bt_clock_snapshot
*cs
;
1942 bt_message_stream_clock_snapshot_state cs_state
=
1943 bt_message_stream_beginning_borrow_default_clock_snapshot_const(msg
, &cs
);
1945 if (cs_state
== BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN
) {
1946 write_time(ctx
, cs
);
1948 write_time_str(ctx
, "Unknown");
1952 /* Write follow tag for message */
1953 ret
= write_message_follow_tag(ctx
, stream
);
1958 /* Write stream properties */
1959 write_obj_type_name(ctx
, "Stream beginning");
1961 if (ctx
->details_comp
->cfg
.compact
) {
1966 g_string_append(ctx
->str
, ":\n");
1969 if (ctx
->details_comp
->cfg
.with_stream_name
) {
1970 name
= bt_stream_get_name(stream
);
1972 write_str_prop_line(ctx
, "Name", name
);
1976 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
1977 name
= bt_stream_class_get_name(sc
);
1979 write_str_prop_line(ctx
, "Class name", name
);
1983 write_trace(ctx
, trace
);
1991 int write_stream_end_message(struct details_write_ctx
*ctx
,
1992 const bt_message
*msg
)
1995 const bt_stream
*stream
=
1996 bt_message_stream_end_borrow_stream_const(msg
);
1997 const bt_stream_class
*sc
=
1998 bt_stream_borrow_class_const(stream
);
1999 const bt_clock_class
*cc
=
2000 bt_stream_class_borrow_default_clock_class_const(sc
);
2004 const bt_clock_snapshot
*cs
;
2005 bt_message_stream_clock_snapshot_state cs_state
=
2006 bt_message_stream_end_borrow_default_clock_snapshot_const(msg
, &cs
);
2008 if (cs_state
== BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN
) {
2009 write_time(ctx
, cs
);
2011 write_time_str(ctx
, "Unknown");
2015 /* Write follow tag for message */
2016 ret
= write_message_follow_tag(ctx
, stream
);
2021 /* Write stream properties */
2022 write_obj_type_name(ctx
, "Stream end\n");
2029 int write_packet_beginning_message(struct details_write_ctx
*ctx
,
2030 const bt_message
*msg
)
2033 const bt_packet
*packet
=
2034 bt_message_packet_beginning_borrow_packet_const(msg
);
2035 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
2036 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2037 const bt_field
*field
;
2040 if (bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
)) {
2042 bt_message_packet_beginning_borrow_default_clock_snapshot_const(
2046 /* Write follow tag for message */
2047 ret
= write_message_follow_tag(ctx
, stream
);
2052 write_obj_type_name(ctx
, "Packet beginning");
2054 if (ctx
->details_comp
->cfg
.compact
) {
2060 g_string_append(ctx
->str
, ":\n");
2062 field
= bt_packet_borrow_context_field_const(packet
);
2064 write_root_field(ctx
, "Context", field
);
2074 int write_discarded_items_message(struct details_write_ctx
*ctx
,
2075 const char *name
, const bt_stream
*stream
,
2076 const bt_clock_snapshot
*beginning_cs
,
2077 const bt_clock_snapshot
*end_cs
, uint64_t count
)
2083 write_time(ctx
, beginning_cs
);
2085 write_time(ctx
, end_cs
);
2088 /* Write follow tag for message */
2089 ret
= write_message_follow_tag(ctx
, stream
);
2094 write_obj_type_name(ctx
, "Discarded ");
2095 write_obj_type_name(ctx
, name
);
2098 if (count
== UINT64_C(-1)) {
2103 g_string_append(ctx
->str
, " (");
2104 write_uint_prop_value(ctx
, count
);
2105 g_string_append_printf(ctx
->str
, " %s)\n", name
);
2112 int write_discarded_events_message(struct details_write_ctx
*ctx
,
2113 const bt_message
*msg
)
2115 const bt_stream
*stream
= bt_message_discarded_events_borrow_stream_const(
2117 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2118 const bt_clock_snapshot
*beginning_cs
= NULL
;
2119 const bt_clock_snapshot
*end_cs
= NULL
;
2122 if (bt_stream_class_discarded_events_have_default_clock_snapshots(sc
)) {
2124 bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
2127 bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
2131 if (bt_message_discarded_events_get_count(msg
, &count
) !=
2132 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2133 count
= UINT64_C(-1);
2136 return write_discarded_items_message(ctx
, "events", stream
,
2137 beginning_cs
, end_cs
, count
);
2141 int write_discarded_packets_message(struct details_write_ctx
*ctx
,
2142 const bt_message
*msg
)
2144 const bt_stream
*stream
= bt_message_discarded_packets_borrow_stream_const(
2146 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2147 const bt_clock_snapshot
*beginning_cs
= NULL
;
2148 const bt_clock_snapshot
*end_cs
= NULL
;
2151 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
)) {
2153 bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
2156 bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
2160 if (bt_message_discarded_packets_get_count(msg
, &count
) !=
2161 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2162 count
= UINT64_C(-1);
2165 return write_discarded_items_message(ctx
, "packets", stream
,
2166 beginning_cs
, end_cs
, count
);
2170 int write_packet_end_message(struct details_write_ctx
*ctx
,
2171 const bt_message
*msg
)
2174 const bt_packet
*packet
=
2175 bt_message_packet_end_borrow_packet_const(msg
);
2176 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
2177 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2180 if (bt_stream_class_packets_have_end_default_clock_snapshot(sc
)) {
2182 bt_message_packet_end_borrow_default_clock_snapshot_const(
2186 /* Write follow tag for message */
2187 ret
= write_message_follow_tag(ctx
, stream
);
2192 write_obj_type_name(ctx
, "Packet end");
2200 int write_message_iterator_inactivity_message(struct details_write_ctx
*ctx
,
2201 const bt_message
*msg
)
2204 const bt_clock_snapshot
*cs
=
2205 bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const(
2209 write_time(ctx
, cs
);
2210 write_obj_type_name(ctx
, "Message iterator inactivity");
2212 if (ctx
->details_comp
->cfg
.compact
) {
2217 /* Write clock class properties */
2218 g_string_append(ctx
->str
, ":\n");
2221 write_prop_name(ctx
, "Clock class");
2222 g_string_append_c(ctx
->str
, ':');
2225 write_clock_class_prop_lines(ctx
,
2226 bt_clock_snapshot_borrow_clock_class_const(cs
));
2234 int details_write_message(struct details_comp
*details_comp
,
2235 const bt_message
*msg
)
2238 struct details_write_ctx ctx
= {
2239 .details_comp
= details_comp
,
2240 .str
= details_comp
->str
,
2244 /* Reset output buffer */
2245 g_string_assign(details_comp
->str
, "");
2247 if (details_comp
->printed_something
&& !details_comp
->cfg
.compact
) {
2251 switch (bt_message_get_type(msg
)) {
2252 case BT_MESSAGE_TYPE_EVENT
:
2253 ret
= write_event_message(&ctx
, msg
);
2255 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
:
2256 ret
= write_message_iterator_inactivity_message(&ctx
, msg
);
2258 case BT_MESSAGE_TYPE_STREAM_BEGINNING
:
2259 ret
= write_stream_beginning_message(&ctx
, msg
);
2261 case BT_MESSAGE_TYPE_STREAM_END
:
2262 ret
= write_stream_end_message(&ctx
, msg
);
2264 case BT_MESSAGE_TYPE_PACKET_BEGINNING
:
2265 ret
= write_packet_beginning_message(&ctx
, msg
);
2267 case BT_MESSAGE_TYPE_PACKET_END
:
2268 ret
= write_packet_end_message(&ctx
, msg
);
2270 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
2271 ret
= write_discarded_events_message(&ctx
, msg
);
2273 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
2274 ret
= write_discarded_packets_message(&ctx
, msg
);