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
,
208 format_uint(buf
, index
, 10);
209 g_string_append_printf(ctx
->str
, "%s[%s]%s:",
210 color
, buf
, color_reset(ctx
));
214 void write_obj_type_name(struct details_write_ctx
*ctx
, const char *name
)
216 g_string_append_printf(ctx
->str
, "%s%s%s%s",
217 color_fg_yellow(ctx
), color_bold(ctx
), name
, color_reset(ctx
));
221 void write_prop_name(struct details_write_ctx
*ctx
, const char *prop_name
)
223 g_string_append_printf(ctx
->str
, "%s%s%s",
224 color_fg_magenta(ctx
), prop_name
, color_reset(ctx
));
228 void write_prop_name_line(struct details_write_ctx
*ctx
, const char *prop_name
)
231 g_string_append_printf(ctx
->str
, "%s%s%s:",
232 color_fg_magenta(ctx
), prop_name
, color_reset(ctx
));
236 void write_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
238 g_string_append_printf(ctx
->str
, "%s%s%s",
239 color_bold(ctx
), value
, color_reset(ctx
));
243 void write_none_prop_value(struct details_write_ctx
*ctx
, const char *value
)
245 g_string_append_printf(ctx
->str
, "%s%s%s%s",
246 color_bold(ctx
), color_fg_magenta(ctx
),
247 value
, color_reset(ctx
));
251 void write_uint_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
253 write_str_prop_value(ctx
, value
);
257 void write_uint_prop_value(struct details_write_ctx
*ctx
, uint64_t value
)
261 format_uint(buf
, value
, 10);
262 write_uint_str_prop_value(ctx
, buf
);
266 void write_int_prop_value(struct details_write_ctx
*ctx
, int64_t value
)
270 format_int(buf
, value
, 10);
271 write_uint_str_prop_value(ctx
, buf
);
275 void write_float_prop_value(struct details_write_ctx
*ctx
, double value
)
277 g_string_append_printf(ctx
->str
, "%s%f%s",
278 color_bold(ctx
), value
, color_reset(ctx
));
282 void write_str_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
283 const char *prop_value
)
285 BT_ASSERT(prop_value
);
287 write_prop_name(ctx
, prop_name
);
288 g_string_append(ctx
->str
, ": ");
289 write_str_prop_value(ctx
, prop_value
);
294 void write_uint_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
298 write_prop_name(ctx
, prop_name
);
299 g_string_append(ctx
->str
, ": ");
300 write_uint_prop_value(ctx
, prop_value
);
305 void write_int_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
309 write_prop_name(ctx
, prop_name
);
310 g_string_append(ctx
->str
, ": ");
311 write_int_prop_value(ctx
, prop_value
);
316 void write_int_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
318 write_str_prop_value(ctx
, value
);
322 void write_bool_prop_value(struct details_write_ctx
*ctx
, bt_bool prop_value
)
326 g_string_append(ctx
->str
, color_bold(ctx
));
329 g_string_append(ctx
->str
, color_fg_green(ctx
));
332 g_string_append(ctx
->str
, color_fg_red(ctx
));
336 g_string_append_printf(ctx
->str
, "%s%s", str
, color_reset(ctx
));
340 void write_bool_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
344 write_prop_name(ctx
, prop_name
);
345 g_string_append(ctx
->str
, ": ");
346 write_bool_prop_value(ctx
, prop_value
);
351 void write_uuid_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
356 write_prop_name(ctx
, prop_name
);
357 g_string_append_printf(ctx
->str
,
358 ": %s" BT_UUID_FMT
"%s\n",
360 BT_UUID_FMT_VALUES(uuid
),
365 gint
compare_strings(const char **a
, const char **b
)
367 return strcmp(*a
, *b
);
371 bt_bool
map_value_foreach_add_key_to_array(const char *key
,
372 const bt_value
*object
, void *data
)
374 GPtrArray
*keys
= data
;
377 g_ptr_array_add(keys
, (void *) key
);
382 void write_value(struct details_write_ctx
*ctx
, const bt_value
*value
,
386 bt_value_type value_type
= bt_value_get_type(value
);
387 GPtrArray
*keys
= g_ptr_array_new();
392 /* Write field's name */
394 write_prop_name_line(ctx
, name
);
397 /* Write field's value */
398 switch (value_type
) {
399 case BT_VALUE_TYPE_NULL
:
401 write_none_prop_value(ctx
, "Null");
403 case BT_VALUE_TYPE_BOOL
:
405 write_bool_prop_value(ctx
, bt_value_bool_get(value
));
407 case BT_VALUE_TYPE_UNSIGNED_INTEGER
:
408 format_uint(buf
, bt_value_integer_unsigned_get(value
), 10);
410 write_uint_str_prop_value(ctx
, buf
);
412 case BT_VALUE_TYPE_SIGNED_INTEGER
:
413 format_int(buf
, bt_value_integer_signed_get(value
), 10);
415 write_int_str_prop_value(ctx
, buf
);
417 case BT_VALUE_TYPE_REAL
:
419 write_float_prop_value(ctx
, bt_value_real_get(value
));
421 case BT_VALUE_TYPE_STRING
:
423 write_str_prop_value(ctx
, bt_value_string_get(value
));
425 case BT_VALUE_TYPE_ARRAY
:
427 uint64_t length
= bt_value_array_get_length(value
);
431 write_none_prop_value(ctx
, "Empty");
433 g_string_append(ctx
->str
, " Length ");
434 write_uint_prop_value(ctx
, length
);
435 g_string_append_c(ctx
->str
, ':');
440 for (i
= 0; i
< length
; i
++) {
441 const bt_value
*elem_value
=
442 bt_value_array_borrow_element_by_index_const(
446 write_array_index(ctx
, i
, color_fg_magenta(ctx
));
447 write_value(ctx
, elem_value
, NULL
);
453 case BT_VALUE_TYPE_MAP
:
455 bt_value_map_foreach_entry_const_status foreach_status
=
456 bt_value_map_foreach_entry_const(value
,
457 map_value_foreach_add_key_to_array
, keys
);
459 BT_ASSERT(foreach_status
==
460 BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_OK
);
461 g_ptr_array_sort(keys
, (GCompareFunc
) compare_strings
);
466 for (i
= 0; i
< keys
->len
; i
++) {
467 const char *key
= keys
->pdata
[i
];
468 const bt_value
*entry_value
=
469 bt_value_map_borrow_entry_value_const(
473 write_value(ctx
, entry_value
, key
);
479 write_none_prop_value(ctx
, "Empty");
488 g_ptr_array_free(keys
, TRUE
);
492 void write_user_attributes(struct details_write_ctx
*ctx
,
493 const bt_value
*user_attrs
, bool write_newline
, bool *written
)
495 BT_ASSERT(user_attrs
);
497 if (!bt_value_map_is_empty(user_attrs
)) {
498 write_value(ctx
, user_attrs
, "User attributes");
511 void write_int_field_class_props(struct details_write_ctx
*ctx
,
512 const bt_field_class
*fc
, bool close
)
514 g_string_append_printf(ctx
->str
, "(%s%" PRIu64
"-bit%s, Base ",
516 bt_field_class_integer_get_field_value_range(fc
),
519 switch (bt_field_class_integer_get_preferred_display_base(fc
)) {
520 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
521 write_uint_prop_value(ctx
, 2);
523 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
524 write_uint_prop_value(ctx
, 8);
526 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
527 write_uint_prop_value(ctx
, 10);
529 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
530 write_uint_prop_value(ctx
, 16);
537 g_string_append(ctx
->str
, ")");
553 struct enum_field_class_mapping
{
557 /* Array of `struct int_range` */
562 gint
compare_enum_field_class_mappings(struct enum_field_class_mapping
**a
,
563 struct enum_field_class_mapping
**b
)
565 return strcmp((*a
)->label
, (*b
)->label
);
569 gint
compare_int_ranges_signed(struct int_range
*a
, struct int_range
*b
)
572 if (a
->lower
.i
< b
->lower
.i
) {
574 } else if (a
->lower
.i
> b
->lower
.i
) {
577 if (a
->upper
.i
< b
->upper
.i
) {
579 } else if (a
->upper
.i
> b
->upper
.i
) {
588 gint
compare_int_ranges_unsigned(struct int_range
*a
, struct int_range
*b
)
590 if (a
->lower
.u
< b
->lower
.u
) {
592 } else if (a
->lower
.u
> b
->lower
.u
) {
595 if (a
->upper
.u
< b
->upper
.u
) {
597 } else if (a
->upper
.u
> b
->upper
.u
) {
606 GArray
*range_set_to_int_ranges(const void *spec_range_set
, bool is_signed
)
609 const bt_integer_range_set
*range_set
;
610 GArray
*ranges
= g_array_new(FALSE
, TRUE
, sizeof(struct int_range
));
617 range_set
= bt_integer_range_set_signed_as_range_set_const(
620 range_set
= bt_integer_range_set_unsigned_as_range_set_const(
624 for (i
= 0; i
< bt_integer_range_set_get_range_count(range_set
); i
++) {
625 struct int_range range
;
628 const bt_integer_range_signed
*orig_range
=
629 bt_integer_range_set_signed_borrow_range_by_index_const(
632 range
.lower
.i
= bt_integer_range_signed_get_lower(orig_range
);
633 range
.upper
.i
= bt_integer_range_signed_get_upper(orig_range
);
635 const bt_integer_range_unsigned
*orig_range
=
636 bt_integer_range_set_unsigned_borrow_range_by_index_const(
639 range
.lower
.u
= bt_integer_range_unsigned_get_lower(orig_range
);
640 range
.upper
.u
= bt_integer_range_unsigned_get_upper(orig_range
);
643 g_array_append_val(ranges
, range
);
647 g_array_sort(ranges
, (GCompareFunc
) compare_int_ranges_signed
);
650 (GCompareFunc
) compare_int_ranges_unsigned
);
658 void destroy_enum_field_class_mapping(struct enum_field_class_mapping
*mapping
)
660 if (mapping
->ranges
) {
661 g_array_free(mapping
->ranges
, TRUE
);
662 mapping
->ranges
= NULL
;
669 struct int_range
*int_range_at(GArray
*ranges
, uint64_t index
)
671 return &g_array_index(ranges
, struct int_range
, index
);
675 void write_int_range(struct details_write_ctx
*ctx
,
676 struct int_range
*range
, bool is_signed
)
678 g_string_append(ctx
->str
, "[");
681 write_int_prop_value(ctx
, range
->lower
.i
);
683 write_int_prop_value(ctx
, range
->lower
.u
);
686 if (range
->lower
.u
!= range
->upper
.u
) {
687 g_string_append(ctx
->str
, ", ");
690 write_int_prop_value(ctx
, range
->upper
.i
);
692 write_int_prop_value(ctx
, range
->upper
.u
);
696 g_string_append(ctx
->str
, "]");
700 void write_enum_field_class_mappings(struct details_write_ctx
*ctx
,
701 const bt_field_class
*fc
)
706 bool is_signed
= bt_field_class_get_type(fc
) ==
707 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
;
709 mappings
= g_ptr_array_new_with_free_func(
710 (GDestroyNotify
) destroy_enum_field_class_mapping
);
714 * Copy field class's mappings to our own arrays and structures
717 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(fc
); i
++) {
718 const void *fc_mapping
;
719 const void *fc_range_set
;
720 struct enum_field_class_mapping
*mapping
= g_new0(
721 struct enum_field_class_mapping
, 1);
726 fc_mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
728 fc_range_set
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
731 fc_mapping
= bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
733 fc_range_set
= bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
737 mapping
->label
= bt_field_class_enumeration_mapping_get_label(
738 bt_field_class_enumeration_signed_mapping_as_mapping_const(
740 mapping
->ranges
= range_set_to_int_ranges(fc_range_set
,
742 BT_ASSERT(mapping
->ranges
);
743 g_ptr_array_add(mappings
, mapping
);
746 /* Sort mappings (ranges are already sorted within mappings) */
747 g_ptr_array_sort(mappings
,
748 (GCompareFunc
) compare_enum_field_class_mappings
);
751 for (i
= 0; i
< mappings
->len
; i
++) {
752 struct enum_field_class_mapping
*mapping
= mappings
->pdata
[i
];
755 write_prop_name_line(ctx
, mapping
->label
);
757 for (range_i
= 0; range_i
< mapping
->ranges
->len
; range_i
++) {
760 int_range_at(mapping
->ranges
, range_i
),
765 g_ptr_array_free(mappings
, TRUE
);
769 void write_field_path(struct details_write_ctx
*ctx
,
770 const bt_field_path
*field_path
)
774 g_string_append_c(ctx
->str
, '[');
776 switch (bt_field_path_get_root_scope(field_path
)) {
777 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
778 write_str_prop_value(ctx
, "Packet context");
780 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
781 write_str_prop_value(ctx
, "Event common context");
783 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
784 write_str_prop_value(ctx
, "Event specific context");
786 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
787 write_str_prop_value(ctx
, "Event payload");
793 g_string_append(ctx
->str
, ": ");
795 for (i
= 0; i
< bt_field_path_get_item_count(field_path
); i
++) {
796 const bt_field_path_item
*fp_item
=
797 bt_field_path_borrow_item_by_index_const(field_path
, i
);
800 g_string_append(ctx
->str
, ", ");
803 switch (bt_field_path_item_get_type(fp_item
)) {
804 case BT_FIELD_PATH_ITEM_TYPE_INDEX
:
805 write_uint_prop_value(ctx
,
806 bt_field_path_item_index_get_index(fp_item
));
808 case BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
:
809 write_str_prop_value(ctx
, "<current>");
816 g_string_append_c(ctx
->str
, ']');
820 void write_field_class(struct details_write_ctx
*ctx
, const bt_field_class
*fc
);
823 void write_variant_field_class_option(struct details_write_ctx
*ctx
,
824 const bt_field_class
*fc
, uint64_t index
)
826 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
827 const bt_field_class_variant_option
*option
=
828 bt_field_class_variant_borrow_option_by_index_const(
830 const void *orig_ranges
= NULL
;
831 GArray
*int_ranges
= NULL
;
833 const bt_value
*user_attrs
=
834 bt_field_class_variant_option_borrow_user_attributes_const(
836 const bt_field_class
*option_fc
=
837 bt_field_class_variant_option_borrow_field_class_const(option
);
840 write_compound_member_name(ctx
,
841 bt_field_class_variant_option_get_name(option
));
843 if (fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
844 const bt_field_class_variant_with_selector_field_integer_unsigned_option
*spec_opt
=
845 bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const(
849 bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
852 } else if (fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD
) {
853 const bt_field_class_variant_with_selector_field_integer_signed_option
*spec_opt
=
854 bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const(
858 bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const(
866 int_ranges
= range_set_to_int_ranges(orig_ranges
, is_signed
);
867 BT_ASSERT(int_ranges
);
869 for (i
= 0; i
< int_ranges
->len
; i
++) {
870 struct int_range
*range
= int_range_at(int_ranges
, i
);
873 write_int_range(ctx
, range
, is_signed
);
876 g_string_append(ctx
->str
, ": ");
881 if (bt_value_map_is_empty(user_attrs
)) {
882 write_field_class(ctx
, option_fc
);
888 write_prop_name_line(ctx
, "Field class");
890 write_field_class(ctx
, option_fc
);
893 /* User attributes */
894 write_user_attributes(ctx
, user_attrs
,
901 g_array_free(int_ranges
, TRUE
);
906 void write_field_class(struct details_write_ctx
*ctx
, const bt_field_class
*fc
)
910 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
911 const bt_value
*user_attrs
;
912 bool wrote_user_attrs
= false;
914 /* Write field class's type */
916 case BT_FIELD_CLASS_TYPE_BOOL
:
919 case BT_FIELD_CLASS_TYPE_BIT_ARRAY
:
922 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
923 type
= "Unsigned integer";
925 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
926 type
= "Signed integer";
928 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
929 type
= "Unsigned enumeration";
931 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
932 type
= "Signed enumeration";
934 case BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
:
935 type
= "Single-precision real";
937 case BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL
:
938 type
= "Double-precision real";
940 case BT_FIELD_CLASS_TYPE_STRING
:
943 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
946 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
947 type
= "Static array";
949 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD
:
950 type
= "Dynamic array (no length field)";
952 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
:
953 type
= "Dynamic array (with length field)";
955 case BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD
:
956 type
= "Option (no selector)";
958 case BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD
:
959 type
= "Option (boolean selector)";
961 case BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
962 type
= "Option (unsigned integer selector)";
964 case BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
965 type
= "Option (signed integer selector)";
967 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
:
968 type
= "Variant (no selector)";
970 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
971 type
= "Variant (unsigned integer selector)";
973 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
974 type
= "Variant (signed integer selector)";
980 g_string_append_printf(ctx
->str
, "%s%s%s",
981 color_fg_blue(ctx
), type
, color_reset(ctx
));
983 /* Write field class's single-line properties */
985 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
986 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
988 write_int_field_class_props(ctx
, fc
, true);
990 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
991 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
993 uint64_t mapping_count
=
994 bt_field_class_enumeration_get_mapping_count(fc
);
997 write_int_field_class_props(ctx
, fc
, false);
998 g_string_append(ctx
->str
, ", ");
999 write_uint_prop_value(ctx
, mapping_count
);
1000 g_string_append_printf(ctx
->str
, " mapping%s)",
1001 plural(mapping_count
));
1004 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1006 uint64_t member_count
=
1007 bt_field_class_structure_get_member_count(fc
);
1009 g_string_append(ctx
->str
, " (");
1010 write_uint_prop_value(ctx
, member_count
);
1011 g_string_append_printf(ctx
->str
, " member%s)",
1012 plural(member_count
));
1015 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1016 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD
:
1017 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
:
1018 if (fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
1019 g_string_append(ctx
->str
, " (Length ");
1020 write_uint_prop_value(ctx
,
1021 bt_field_class_array_static_get_length(fc
));
1022 g_string_append_c(ctx
->str
, ')');
1023 } else if (fc_type
== BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
) {
1024 const bt_field_path
*length_field_path
=
1025 bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const(
1028 g_string_append(ctx
->str
, " (Length field path ");
1029 write_field_path(ctx
, length_field_path
);
1030 g_string_append_c(ctx
->str
, ')');
1034 case BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD
:
1035 case BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
1036 case BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
1038 const bt_field_path
*selector_field_path
=
1039 bt_field_class_option_with_selector_field_borrow_selector_field_path_const(
1042 g_string_append(ctx
->str
, " (Selector field path ");
1043 write_field_path(ctx
, selector_field_path
);
1044 g_string_append_c(ctx
->str
, ')');
1047 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
:
1048 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
1049 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
1051 uint64_t option_count
=
1052 bt_field_class_variant_get_option_count(fc
);
1053 const bt_field_path
*sel_field_path
= NULL
;
1055 if (fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
||
1056 fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD
) {
1058 bt_field_class_variant_with_selector_field_borrow_selector_field_path_const(
1060 BT_ASSERT(sel_field_path
);
1063 g_string_append(ctx
->str
, " (");
1064 write_uint_prop_value(ctx
, option_count
);
1065 g_string_append_printf(ctx
->str
, " option%s",
1066 plural(option_count
));
1068 if (sel_field_path
) {
1069 g_string_append(ctx
->str
, ", Selector field path ");
1070 write_field_path(ctx
, sel_field_path
);
1073 g_string_append_c(ctx
->str
, ')');
1081 user_attrs
= bt_field_class_borrow_user_attributes_const(fc
);
1082 if (!bt_value_map_is_empty(user_attrs
)) {
1083 g_string_append(ctx
->str
, ":\n");
1084 write_user_attributes(ctx
, user_attrs
, false, NULL
);
1085 wrote_user_attrs
= true;
1088 /* Write field class's complex properties */
1090 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
1091 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
1093 uint64_t mapping_count
=
1094 bt_field_class_enumeration_get_mapping_count(fc
);
1096 if (mapping_count
> 0) {
1097 if (wrote_user_attrs
) {
1100 write_prop_name(ctx
, "Mappings");
1101 g_string_append_c(ctx
->str
, ':');
1104 /* Each mapping starts with its own newline */
1105 g_string_append_c(ctx
->str
, ':');
1108 write_enum_field_class_mappings(ctx
, fc
);
1110 if (wrote_user_attrs
) {
1117 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1119 uint64_t member_count
=
1120 bt_field_class_structure_get_member_count(fc
);
1122 if (member_count
> 0) {
1123 if (wrote_user_attrs
) {
1126 write_prop_name(ctx
, "Members");
1127 g_string_append_c(ctx
->str
, ':');
1130 /* Each member starts with its own newline */
1131 g_string_append_c(ctx
->str
, ':');
1134 for (i
= 0; i
< member_count
; i
++) {
1135 const bt_field_class_structure_member
*member
=
1136 bt_field_class_structure_borrow_member_by_index_const(
1138 const bt_value
*user_attrs
;
1139 const bt_field_class
*member_fc
=
1140 bt_field_class_structure_member_borrow_field_class_const(member
);
1143 write_compound_member_name(ctx
,
1144 bt_field_class_structure_member_get_name(member
));
1145 user_attrs
= bt_field_class_structure_member_borrow_user_attributes_const(
1148 if (bt_value_map_is_empty(user_attrs
)) {
1150 write_field_class(ctx
, member_fc
);
1156 write_prop_name_line(ctx
, "Field class");
1158 write_field_class(ctx
, member_fc
);
1161 /* User attributes */
1162 write_user_attributes(ctx
, user_attrs
,
1169 if (wrote_user_attrs
) {
1176 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1177 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD
:
1178 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
:
1179 if (wrote_user_attrs
) {
1182 g_string_append(ctx
->str
, ":\n");
1185 write_prop_name_line(ctx
, "Element");
1187 write_field_class(ctx
,
1188 bt_field_class_array_borrow_element_field_class_const(fc
));
1190 case BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD
:
1191 case BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD
:
1192 case BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
1193 case BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
1195 const void *ranges
= NULL
;
1196 bool selector_is_signed
= false;
1198 if (wrote_user_attrs
) {
1201 g_string_append(ctx
->str
, ":\n");
1204 if (fc_type
== BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD
) {
1205 write_bool_prop_line(ctx
, "Selector is reversed",
1206 bt_field_class_option_with_selector_field_bool_selector_is_reversed(fc
));
1207 } else if (fc_type
== BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
1208 ranges
= bt_field_class_option_with_selector_field_integer_unsigned_borrow_selector_ranges_const(fc
);
1209 } else if (fc_type
== BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD
) {
1210 ranges
= bt_field_class_option_with_selector_field_integer_signed_borrow_selector_ranges_const(fc
);
1211 selector_is_signed
= true;
1215 GArray
*sorted_ranges
= range_set_to_int_ranges(
1216 ranges
, selector_is_signed
);
1219 BT_ASSERT(sorted_ranges
);
1220 BT_ASSERT(sorted_ranges
->len
> 0);
1221 write_prop_name_line(ctx
, "Selector ranges");
1223 for (i
= 0; i
< sorted_ranges
->len
; i
++) {
1225 write_int_range(ctx
,
1226 int_range_at(sorted_ranges
, i
),
1227 selector_is_signed
);
1231 g_array_free(sorted_ranges
, TRUE
);
1234 write_prop_name_line(ctx
, "Content");
1236 write_field_class(ctx
,
1237 bt_field_class_option_borrow_field_class_const(fc
));
1240 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
:
1241 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
1242 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
1244 uint64_t option_count
=
1245 bt_field_class_variant_get_option_count(fc
);
1247 if (option_count
> 0) {
1248 if (wrote_user_attrs
) {
1251 write_prop_name(ctx
, "Options");
1252 g_string_append_c(ctx
->str
, ':');
1255 /* Each option starts with its own newline */
1256 g_string_append_c(ctx
->str
, ':');
1259 for (i
= 0; i
< option_count
; i
++) {
1260 write_variant_field_class_option(ctx
, fc
, i
);
1263 if (wrote_user_attrs
) {
1278 void write_root_field_class(struct details_write_ctx
*ctx
, const char *name
,
1279 const bt_field_class
*fc
)
1284 write_prop_name(ctx
, name
);
1285 g_string_append(ctx
->str
, ": ");
1286 write_field_class(ctx
, fc
);
1291 void write_event_class(struct details_write_ctx
*ctx
, const bt_event_class
*ec
)
1293 const char *name
= bt_event_class_get_name(ec
);
1294 const char *emf_uri
;
1295 const bt_field_class
*fc
;
1296 bt_event_class_log_level log_level
;
1299 write_obj_type_name(ctx
, "Event class");
1301 /* Write name and ID */
1303 g_string_append_printf(ctx
->str
, " `%s%s%s`",
1304 color_fg_green(ctx
), name
, color_reset(ctx
));
1307 g_string_append(ctx
->str
, " (ID ");
1308 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
1309 g_string_append(ctx
->str
, "):\n");
1311 /* Write properties */
1314 /* Write user attributes */
1315 write_user_attributes(ctx
,
1316 bt_event_class_borrow_user_attributes_const(ec
), true, NULL
);
1318 /* Write log level */
1319 if (bt_event_class_get_log_level(ec
, &log_level
) ==
1320 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
1321 const char *ll_str
= NULL
;
1323 switch (log_level
) {
1324 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
1325 ll_str
= "Emergency";
1327 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
1330 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
1331 ll_str
= "Critical";
1333 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
1336 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
1339 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
1342 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
1345 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
1346 ll_str
= "Debug (system)";
1348 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
1349 ll_str
= "Debug (program)";
1351 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
1352 ll_str
= "Debug (process)";
1354 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
1355 ll_str
= "Debug (module)";
1357 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
1358 ll_str
= "Debug (unit)";
1360 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
1361 ll_str
= "Debug (function)";
1363 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
1364 ll_str
= "Debug (line)";
1366 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
1373 write_str_prop_line(ctx
, "Log level", ll_str
);
1377 emf_uri
= bt_event_class_get_emf_uri(ec
);
1379 write_str_prop_line(ctx
, "EMF URI", emf_uri
);
1382 /* Write specific context field class */
1383 fc
= bt_event_class_borrow_specific_context_field_class_const(ec
);
1385 write_root_field_class(ctx
, "Specific context field class", fc
);
1388 /* Write payload field class */
1389 fc
= bt_event_class_borrow_payload_field_class_const(ec
);
1391 write_root_field_class(ctx
, "Payload field class", fc
);
1398 void write_clock_class_prop_lines(struct details_write_ctx
*ctx
,
1399 const bt_clock_class
*cc
)
1401 int64_t offset_seconds
;
1402 uint64_t offset_cycles
;
1405 str
= bt_clock_class_get_name(cc
);
1407 write_str_prop_line(ctx
, "Name", str
);
1410 write_user_attributes(ctx
,
1411 bt_clock_class_borrow_user_attributes_const(cc
), true, NULL
);
1412 str
= bt_clock_class_get_description(cc
);
1414 write_str_prop_line(ctx
, "Description", str
);
1417 write_uint_prop_line(ctx
, "Frequency (Hz)",
1418 bt_clock_class_get_frequency(cc
));
1419 write_uint_prop_line(ctx
, "Precision (cycles)",
1420 bt_clock_class_get_precision(cc
));
1421 bt_clock_class_get_offset(cc
, &offset_seconds
, &offset_cycles
);
1422 write_int_prop_line(ctx
, "Offset (s)", offset_seconds
);
1423 write_uint_prop_line(ctx
, "Offset (cycles)", offset_cycles
);
1424 write_bool_prop_line(ctx
, "Origin is Unix epoch",
1425 bt_clock_class_origin_is_unix_epoch(cc
));
1427 if (ctx
->details_comp
->cfg
.with_uuid
) {
1428 bt_uuid uuid
= bt_clock_class_get_uuid(cc
);
1431 write_uuid_prop_line(ctx
, "UUID", uuid
);
1437 gint
compare_event_classes(const bt_event_class
**a
, const bt_event_class
**b
)
1439 uint64_t id_a
= bt_event_class_get_id(*a
);
1440 uint64_t id_b
= bt_event_class_get_id(*b
);
1444 } else if (id_a
> id_b
) {
1452 void write_stream_class(struct details_write_ctx
*ctx
,
1453 const bt_stream_class
*sc
)
1455 const bt_field_class
*fc
;
1456 GPtrArray
*event_classes
= g_ptr_array_new();
1460 write_obj_type_name(ctx
, "Stream class");
1462 /* Write name and ID */
1463 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
1464 const char *name
= bt_stream_class_get_name(sc
);
1467 g_string_append(ctx
->str
, " `");
1468 write_str_prop_value(ctx
, name
);
1469 g_string_append(ctx
->str
, "`");
1473 g_string_append(ctx
->str
, " (ID ");
1474 write_uint_prop_value(ctx
, bt_stream_class_get_id(sc
));
1475 g_string_append(ctx
->str
, "):\n");
1477 /* Write properties */
1480 /* Write user attributes */
1481 write_user_attributes(ctx
,
1482 bt_stream_class_borrow_user_attributes_const(sc
), true, NULL
);
1484 /* Write configuration */
1485 write_bool_prop_line(ctx
,
1486 "Supports packets", bt_stream_class_supports_packets(sc
));
1488 if (bt_stream_class_supports_packets(sc
)) {
1489 write_bool_prop_line(ctx
,
1490 "Packets have beginning default clock snapshot",
1491 bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
));
1492 write_bool_prop_line(ctx
,
1493 "Packets have end default clock snapshot",
1494 bt_stream_class_packets_have_end_default_clock_snapshot(sc
));
1497 write_bool_prop_line(ctx
,
1498 "Supports discarded events",
1499 bt_stream_class_supports_discarded_events(sc
));
1501 if (bt_stream_class_supports_discarded_events(sc
)) {
1502 write_bool_prop_line(ctx
,
1503 "Discarded events have default clock snapshots",
1504 bt_stream_class_discarded_events_have_default_clock_snapshots(sc
));
1507 write_bool_prop_line(ctx
,
1508 "Supports discarded packets",
1509 bt_stream_class_supports_discarded_packets(sc
));
1511 if (bt_stream_class_supports_discarded_packets(sc
)) {
1512 write_bool_prop_line(ctx
,
1513 "Discarded packets have default clock snapshots",
1514 bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
));
1517 /* Write default clock class */
1518 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
1520 write_prop_name(ctx
, "Default clock class");
1521 g_string_append_c(ctx
->str
, ':');
1524 write_clock_class_prop_lines(ctx
,
1525 bt_stream_class_borrow_default_clock_class_const(sc
));
1529 fc
= bt_stream_class_borrow_packet_context_field_class_const(sc
);
1531 write_root_field_class(ctx
, "Packet context field class", fc
);
1534 fc
= bt_stream_class_borrow_event_common_context_field_class_const(sc
);
1536 write_root_field_class(ctx
, "Event common context field class",
1540 for (i
= 0; i
< bt_stream_class_get_event_class_count(sc
); i
++) {
1541 g_ptr_array_add(event_classes
,
1542 (gpointer
) bt_stream_class_borrow_event_class_by_index_const(
1546 g_ptr_array_sort(event_classes
, (GCompareFunc
) compare_event_classes
);
1548 for (i
= 0; i
< event_classes
->len
; i
++) {
1549 write_event_class(ctx
, event_classes
->pdata
[i
]);
1553 g_ptr_array_free(event_classes
, TRUE
);
1557 gint
compare_stream_classes(const bt_stream_class
**a
, const bt_stream_class
**b
)
1559 uint64_t id_a
= bt_stream_class_get_id(*a
);
1560 uint64_t id_b
= bt_stream_class_get_id(*b
);
1564 } else if (id_a
> id_b
) {
1572 void write_trace_class(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
)
1574 GPtrArray
*stream_classes
= g_ptr_array_new();
1576 bool printed_prop
= false;
1579 write_obj_type_name(ctx
, "Trace class");
1582 for (i
= 0; i
< bt_trace_class_get_stream_class_count(tc
); i
++) {
1583 g_ptr_array_add(stream_classes
,
1584 (gpointer
) bt_trace_class_borrow_stream_class_by_index_const(
1588 g_ptr_array_sort(stream_classes
, (GCompareFunc
) compare_stream_classes
);
1590 if (stream_classes
->len
> 0) {
1591 if (!printed_prop
) {
1592 g_string_append(ctx
->str
, ":\n");
1593 printed_prop
= true;
1599 /* Write user attributes */
1600 write_user_attributes(ctx
,
1601 bt_trace_class_borrow_user_attributes_const(tc
), true,
1604 /* Write stream classes */
1605 for (i
= 0; i
< stream_classes
->len
; i
++) {
1606 write_stream_class(ctx
, stream_classes
->pdata
[i
]);
1609 if (!printed_prop
) {
1614 g_ptr_array_free(stream_classes
, TRUE
);
1618 int try_write_meta(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
,
1619 const bt_stream_class
*sc
, const bt_event_class
*ec
)
1625 if (details_need_to_write_trace_class(ctx
, tc
)) {
1628 if (ctx
->details_comp
->cfg
.compact
&&
1629 ctx
->details_comp
->printed_something
) {
1631 * There are no empty line between messages in
1632 * compact mode, so write one here to decouple
1633 * the trace class from the next message.
1639 * write_trace_class() also writes all its stream
1640 * classes their event classes, so we don't need to
1643 write_trace_class(ctx
, tc
);
1646 * Mark this trace class as written, as well as all
1647 * its stream classes and their event classes.
1649 ret
= details_did_write_trace_class(ctx
, tc
);
1654 for (sc_i
= 0; sc_i
< bt_trace_class_get_stream_class_count(tc
);
1657 const bt_stream_class
*tc_sc
=
1658 bt_trace_class_borrow_stream_class_by_index_const(
1661 details_did_write_meta_object(ctx
, tc
, tc_sc
);
1663 for (ec_i
= 0; ec_i
<
1664 bt_stream_class_get_event_class_count(tc_sc
);
1666 details_did_write_meta_object(ctx
, tc
,
1667 bt_stream_class_borrow_event_class_by_index_const(
1675 if (sc
&& details_need_to_write_meta_object(ctx
, tc
, sc
)) {
1680 if (ctx
->details_comp
->cfg
.compact
&&
1681 ctx
->details_comp
->printed_something
) {
1683 * There are no empty line between messages in
1684 * compact mode, so write one here to decouple
1685 * the stream class from the next message.
1691 * write_stream_class() also writes all its event
1692 * classes, so we don't need to rewrite `ec`.
1694 write_stream_class(ctx
, sc
);
1697 * Mark this stream class as written, as well as all its
1700 details_did_write_meta_object(ctx
, tc
, sc
);
1702 for (ec_i
= 0; ec_i
<
1703 bt_stream_class_get_event_class_count(sc
);
1705 details_did_write_meta_object(ctx
, tc
,
1706 bt_stream_class_borrow_event_class_by_index_const(
1713 if (ec
&& details_need_to_write_meta_object(ctx
, tc
, ec
)) {
1716 if (ctx
->details_comp
->cfg
.compact
&&
1717 ctx
->details_comp
->printed_something
) {
1719 * There are no empty line between messages in
1720 * compact mode, so write one here to decouple
1721 * the event class from the next message.
1726 write_event_class(ctx
, ec
);
1727 details_did_write_meta_object(ctx
, tc
, ec
);
1736 void write_time_str(struct details_write_ctx
*ctx
, const char *str
)
1738 if (!ctx
->details_comp
->cfg
.with_time
) {
1742 g_string_append_printf(ctx
->str
, "[%s%s%s%s]",
1743 color_bold(ctx
), color_fg_blue(ctx
), str
, color_reset(ctx
));
1745 if (ctx
->details_comp
->cfg
.compact
) {
1756 void write_time(struct details_write_ctx
*ctx
, const bt_clock_snapshot
*cs
)
1758 bt_clock_snapshot_get_ns_from_origin_status cs_status
;
1759 int64_t ns_from_origin
;
1762 if (!ctx
->details_comp
->cfg
.with_time
) {
1766 format_uint(buf
, bt_clock_snapshot_get_value(cs
), 10);
1767 g_string_append_printf(ctx
->str
, "[%s%s%s%s%s",
1768 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1770 ctx
->details_comp
->cfg
.compact
? "" : " cycles");
1771 cs_status
= bt_clock_snapshot_get_ns_from_origin(cs
, &ns_from_origin
);
1772 if (cs_status
== BT_CLOCK_SNAPSHOT_GET_NS_FROM_ORIGIN_STATUS_OK
) {
1773 format_int(buf
, ns_from_origin
, 10);
1774 g_string_append_printf(ctx
->str
, "%s %s%s%s%s%s",
1775 ctx
->details_comp
->cfg
.compact
? "" : ",",
1776 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1778 ctx
->details_comp
->cfg
.compact
? "" : " ns from origin");
1781 g_string_append(ctx
->str
, "]");
1783 if (ctx
->details_comp
->cfg
.compact
) {
1794 int write_message_follow_tag(struct details_write_ctx
*ctx
,
1795 const bt_stream
*stream
)
1798 uint64_t unique_trace_id
;
1799 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1800 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
1802 ret
= details_trace_unique_id(ctx
, trace
, &unique_trace_id
);
1807 if (ctx
->details_comp
->cfg
.compact
) {
1808 g_string_append_printf(ctx
->str
,
1809 "%s{%s%" PRIu64
" %" PRIu64
" %" PRIu64
"%s%s}%s ",
1810 color_fg_cyan(ctx
), color_bold(ctx
),
1811 unique_trace_id
, bt_stream_class_get_id(sc
),
1812 bt_stream_get_id(stream
),
1813 color_reset(ctx
), color_fg_cyan(ctx
), color_reset(ctx
));
1815 g_string_append_printf(ctx
->str
,
1816 "%s{Trace %s%" PRIu64
"%s%s, Stream class ID %s%" PRIu64
"%s%s, Stream ID %s%" PRIu64
"%s%s}%s\n",
1818 color_bold(ctx
), unique_trace_id
,
1819 color_reset(ctx
), color_fg_cyan(ctx
),
1820 color_bold(ctx
), bt_stream_class_get_id(sc
),
1821 color_reset(ctx
), color_fg_cyan(ctx
),
1822 color_bold(ctx
), bt_stream_get_id(stream
),
1823 color_reset(ctx
), color_fg_cyan(ctx
),
1832 void write_field(struct details_write_ctx
*ctx
, const bt_field
*field
,
1836 bt_field_class_type fc_type
= bt_field_get_class_type(field
);
1837 const bt_field_class
*fc
;
1840 /* Write field's name */
1842 write_compound_member_name(ctx
, name
);
1845 /* Write field's value */
1847 case BT_FIELD_CLASS_TYPE_BOOL
:
1849 write_bool_prop_value(ctx
, bt_field_bool_get_value(field
));
1851 case BT_FIELD_CLASS_TYPE_BIT_ARRAY
:
1852 format_uint(buf
, bt_field_bit_array_get_value_as_integer(field
),
1855 write_uint_str_prop_value(ctx
, buf
);
1857 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
1858 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
1859 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
1860 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
1862 unsigned int fmt_base
;
1863 bt_field_class_integer_preferred_display_base base
;
1865 fc
= bt_field_borrow_class_const(field
);
1866 base
= bt_field_class_integer_get_preferred_display_base(fc
);
1869 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
1872 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
1875 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
1878 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
1885 if (fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
1886 fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
1888 bt_field_integer_unsigned_get_value(field
),
1891 write_uint_str_prop_value(ctx
, buf
);
1894 bt_field_integer_signed_get_value(field
),
1897 write_int_str_prop_value(ctx
, buf
);
1902 case BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
:
1904 write_float_prop_value(ctx
, bt_field_real_single_precision_get_value(field
));
1906 case BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL
:
1908 write_float_prop_value(ctx
, bt_field_real_double_precision_get_value(field
));
1910 case BT_FIELD_CLASS_TYPE_STRING
:
1912 write_str_prop_value(ctx
, bt_field_string_get_value(field
));
1914 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1916 uint64_t member_count
;
1918 fc
= bt_field_borrow_class_const(field
);
1919 member_count
= bt_field_class_structure_get_member_count(fc
);
1921 if (member_count
> 0) {
1924 for (i
= 0; i
< member_count
; i
++) {
1925 const bt_field_class_structure_member
*member
=
1926 bt_field_class_structure_borrow_member_by_index_const(
1928 const bt_field
*member_field
=
1929 bt_field_structure_borrow_member_field_by_index_const(
1933 write_field(ctx
, member_field
,
1934 bt_field_class_structure_member_get_name(member
));
1940 write_none_prop_value(ctx
, "Empty");
1945 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1946 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD
:
1947 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
:
1949 uint64_t length
= bt_field_array_get_length(field
);
1953 write_none_prop_value(ctx
, "Empty");
1955 g_string_append(ctx
->str
, " Length ");
1956 write_uint_prop_value(ctx
, length
);
1957 g_string_append_c(ctx
->str
, ':');
1962 for (i
= 0; i
< length
; i
++) {
1963 const bt_field
*elem_field
=
1964 bt_field_array_borrow_element_field_by_index_const(
1968 write_array_index(ctx
, i
, color_fg_cyan(ctx
));
1969 write_field(ctx
, elem_field
, NULL
);
1975 case BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD
:
1976 case BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD
:
1977 case BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
1978 case BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
1980 const bt_field
*content_field
=
1981 bt_field_option_borrow_field_const(field
);
1983 if (!content_field
) {
1985 write_none_prop_value(ctx
, "None");
1987 write_field(ctx
, content_field
, NULL
);
1992 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
:
1993 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
1994 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
1996 bt_field_variant_borrow_selected_option_field_const(
2005 void write_root_field(struct details_write_ctx
*ctx
, const char *name
,
2006 const bt_field
*field
)
2011 write_prop_name(ctx
, name
);
2012 g_string_append(ctx
->str
, ":");
2013 write_field(ctx
, field
, NULL
);
2018 int write_event_message(struct details_write_ctx
*ctx
,
2019 const bt_message
*msg
)
2022 const bt_event
*event
= bt_message_event_borrow_event_const(msg
);
2023 const bt_stream
*stream
= bt_event_borrow_stream_const(event
);
2024 const bt_event_class
*ec
= bt_event_borrow_class_const(event
);
2025 const bt_stream_class
*sc
= bt_event_class_borrow_stream_class_const(ec
);
2026 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
2027 const char *ec_name
;
2028 const bt_field
*field
;
2030 ret
= try_write_meta(ctx
, tc
, sc
, ec
);
2035 if (!ctx
->details_comp
->cfg
.with_data
) {
2039 if (ctx
->str
->len
> 0) {
2041 * Output buffer contains metadata: separate blocks with
2048 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
2050 bt_message_event_borrow_default_clock_snapshot_const(
2054 /* Write follow tag for message */
2055 ret
= write_message_follow_tag(ctx
, stream
);
2060 /* Write object's basic properties */
2061 write_obj_type_name(ctx
, "Event");
2062 ec_name
= bt_event_class_get_name(ec
);
2064 g_string_append_printf(ctx
->str
, " `%s%s%s`",
2065 color_fg_green(ctx
), ec_name
, color_reset(ctx
));
2068 g_string_append(ctx
->str
, " (");
2070 if (!ctx
->details_comp
->cfg
.compact
) {
2071 g_string_append(ctx
->str
, "Class ID ");
2074 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
2075 g_string_append(ctx
->str
, ")");
2077 if (ctx
->details_comp
->cfg
.compact
) {
2083 g_string_append(ctx
->str
, ":\n");
2085 field
= bt_event_borrow_common_context_field_const(event
);
2087 write_root_field(ctx
, "Common context", field
);
2090 field
= bt_event_borrow_specific_context_field_const(event
);
2092 write_root_field(ctx
, "Specific context", field
);
2095 field
= bt_event_borrow_payload_field_const(event
);
2097 write_root_field(ctx
, "Payload", field
);
2107 gint
compare_streams(const bt_stream
**a
, const bt_stream
**b
)
2109 uint64_t id_a
= bt_stream_get_id(*a
);
2110 uint64_t id_b
= bt_stream_get_id(*b
);
2114 } else if (id_a
> id_b
) {
2117 const bt_stream_class
*a_sc
= bt_stream_borrow_class_const(*a
);
2118 const bt_stream_class
*b_sc
= bt_stream_borrow_class_const(*b
);
2119 uint64_t a_sc_id
= bt_stream_class_get_id(a_sc
);
2120 uint64_t b_sc_id
= bt_stream_class_get_id(b_sc
);
2122 if (a_sc_id
< b_sc_id
) {
2124 } else if (a_sc_id
> b_sc_id
) {
2133 void write_trace(struct details_write_ctx
*ctx
, const bt_trace
*trace
)
2136 GPtrArray
*streams
= g_ptr_array_new();
2138 bool printed_prop
= false;
2139 GPtrArray
*env_names
= g_ptr_array_new();
2143 write_obj_type_name(ctx
, "Trace");
2146 if (ctx
->details_comp
->cfg
.with_trace_name
) {
2147 name
= bt_trace_get_name(trace
);
2149 g_string_append(ctx
->str
, " `");
2150 write_str_prop_value(ctx
, name
);
2151 g_string_append(ctx
->str
, "`");
2155 /* Write properties */
2159 if (ctx
->details_comp
->cfg
.with_uuid
) {
2160 bt_uuid uuid
= bt_trace_get_uuid(trace
);
2163 if (!printed_prop
) {
2164 g_string_append(ctx
->str
, ":\n");
2165 printed_prop
= true;
2168 write_uuid_prop_line(ctx
, "UUID", uuid
);
2172 /* Write environment */
2173 env_count
= bt_trace_get_environment_entry_count(trace
);
2174 if (env_count
> 0) {
2175 if (!printed_prop
) {
2176 g_string_append(ctx
->str
, ":\n");
2177 printed_prop
= true;
2181 write_prop_name(ctx
, "Environment");
2182 g_string_append(ctx
->str
, " (");
2183 write_uint_prop_value(ctx
, env_count
);
2184 g_string_append_printf(ctx
->str
, " entr%s):",
2185 env_count
== 1 ? "y" : "ies");
2189 for (i
= 0; i
< env_count
; i
++) {
2191 const bt_value
*value
;
2193 bt_trace_borrow_environment_entry_by_index_const(
2194 trace
, i
, &name
, &value
);
2195 g_ptr_array_add(env_names
, (gpointer
) name
);
2198 g_ptr_array_sort(env_names
, (GCompareFunc
) compare_strings
);
2200 for (i
= 0; i
< env_names
->len
; i
++) {
2201 const char *name
= env_names
->pdata
[i
];
2202 const bt_value
*value
=
2203 bt_trace_borrow_environment_entry_value_by_name_const(
2207 write_compound_member_name(ctx
, name
);
2210 if (bt_value_get_type(value
) ==
2211 BT_VALUE_TYPE_SIGNED_INTEGER
) {
2212 write_int_prop_value(ctx
,
2213 bt_value_integer_signed_get(value
));
2214 } else if (bt_value_get_type(value
) ==
2215 BT_VALUE_TYPE_STRING
) {
2216 write_str_prop_value(ctx
,
2217 bt_value_string_get(value
));
2228 for (i
= 0; i
< bt_trace_get_stream_count(trace
); i
++) {
2229 g_ptr_array_add(streams
,
2230 (gpointer
) bt_trace_borrow_stream_by_index_const(
2234 g_ptr_array_sort(streams
, (GCompareFunc
) compare_streams
);
2236 if (streams
->len
> 0 && !printed_prop
) {
2237 g_string_append(ctx
->str
, ":\n");
2238 printed_prop
= true;
2241 for (i
= 0; i
< streams
->len
; i
++) {
2242 const bt_stream
*stream
= streams
->pdata
[i
];
2245 write_obj_type_name(ctx
, "Stream");
2246 g_string_append(ctx
->str
, " (ID ");
2247 write_uint_prop_value(ctx
, bt_stream_get_id(stream
));
2248 g_string_append(ctx
->str
, ", Class ID ");
2249 write_uint_prop_value(ctx
, bt_stream_class_get_id(
2250 bt_stream_borrow_class_const(stream
)));
2251 g_string_append(ctx
->str
, ")");
2257 if (!printed_prop
) {
2261 g_ptr_array_free(streams
, TRUE
);
2262 g_ptr_array_free(env_names
, TRUE
);
2266 int write_stream_beginning_message(struct details_write_ctx
*ctx
,
2267 const bt_message
*msg
)
2270 const bt_stream
*stream
=
2271 bt_message_stream_beginning_borrow_stream_const(msg
);
2272 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
2273 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2274 const bt_clock_class
*cc
= bt_stream_class_borrow_default_clock_class_const(sc
);
2275 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
2278 ret
= try_write_meta(ctx
, tc
, sc
, NULL
);
2283 if (!ctx
->details_comp
->cfg
.with_data
) {
2287 if (ctx
->str
->len
> 0) {
2289 * Output buffer contains metadata: separate blocks with
2297 const bt_clock_snapshot
*cs
;
2298 bt_message_stream_clock_snapshot_state cs_state
=
2299 bt_message_stream_beginning_borrow_default_clock_snapshot_const(msg
, &cs
);
2301 if (cs_state
== BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN
) {
2302 write_time(ctx
, cs
);
2304 write_time_str(ctx
, "Unknown");
2308 /* Write follow tag for message */
2309 ret
= write_message_follow_tag(ctx
, stream
);
2314 /* Write stream properties */
2315 write_obj_type_name(ctx
, "Stream beginning");
2317 if (ctx
->details_comp
->cfg
.compact
) {
2322 g_string_append(ctx
->str
, ":\n");
2325 if (ctx
->details_comp
->cfg
.with_stream_name
) {
2326 name
= bt_stream_get_name(stream
);
2328 write_str_prop_line(ctx
, "Name", name
);
2332 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
2333 name
= bt_stream_class_get_name(sc
);
2335 write_str_prop_line(ctx
, "Class name", name
);
2339 write_trace(ctx
, trace
);
2347 int write_stream_end_message(struct details_write_ctx
*ctx
,
2348 const bt_message
*msg
)
2351 const bt_stream
*stream
=
2352 bt_message_stream_end_borrow_stream_const(msg
);
2353 const bt_stream_class
*sc
=
2354 bt_stream_borrow_class_const(stream
);
2355 const bt_clock_class
*cc
=
2356 bt_stream_class_borrow_default_clock_class_const(sc
);
2358 if (!ctx
->details_comp
->cfg
.with_data
) {
2364 const bt_clock_snapshot
*cs
;
2365 bt_message_stream_clock_snapshot_state cs_state
=
2366 bt_message_stream_end_borrow_default_clock_snapshot_const(msg
, &cs
);
2368 if (cs_state
== BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN
) {
2369 write_time(ctx
, cs
);
2371 write_time_str(ctx
, "Unknown");
2375 /* Write follow tag for message */
2376 ret
= write_message_follow_tag(ctx
, stream
);
2381 /* Write stream properties */
2382 write_obj_type_name(ctx
, "Stream end\n");
2389 int write_packet_beginning_message(struct details_write_ctx
*ctx
,
2390 const bt_message
*msg
)
2393 const bt_packet
*packet
=
2394 bt_message_packet_beginning_borrow_packet_const(msg
);
2395 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
2396 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2397 const bt_field
*field
;
2399 if (!ctx
->details_comp
->cfg
.with_data
) {
2404 if (bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
)) {
2406 bt_message_packet_beginning_borrow_default_clock_snapshot_const(
2410 /* Write follow tag for message */
2411 ret
= write_message_follow_tag(ctx
, stream
);
2416 write_obj_type_name(ctx
, "Packet beginning");
2418 if (ctx
->details_comp
->cfg
.compact
) {
2424 field
= bt_packet_borrow_context_field_const(packet
);
2426 g_string_append(ctx
->str
, ":\n");
2428 write_root_field(ctx
, "Context", field
);
2439 int write_discarded_items_message(struct details_write_ctx
*ctx
,
2440 const char *name
, const bt_stream
*stream
,
2441 const bt_clock_snapshot
*beginning_cs
,
2442 const bt_clock_snapshot
*end_cs
, uint64_t count
)
2448 write_time(ctx
, beginning_cs
);
2450 write_time(ctx
, end_cs
);
2453 /* Write follow tag for message */
2454 ret
= write_message_follow_tag(ctx
, stream
);
2459 write_obj_type_name(ctx
, "Discarded ");
2460 write_obj_type_name(ctx
, name
);
2463 if (count
== UINT64_C(-1)) {
2468 g_string_append(ctx
->str
, " (");
2469 write_uint_prop_value(ctx
, count
);
2470 g_string_append_printf(ctx
->str
, " %s)\n", name
);
2477 int write_discarded_events_message(struct details_write_ctx
*ctx
,
2478 const bt_message
*msg
)
2481 const bt_stream
*stream
= bt_message_discarded_events_borrow_stream_const(
2483 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2484 const bt_clock_snapshot
*beginning_cs
= NULL
;
2485 const bt_clock_snapshot
*end_cs
= NULL
;
2488 if (!ctx
->details_comp
->cfg
.with_data
) {
2492 if (bt_stream_class_discarded_events_have_default_clock_snapshots(sc
)) {
2494 bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
2497 bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
2501 if (bt_message_discarded_events_get_count(msg
, &count
) !=
2502 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2503 count
= UINT64_C(-1);
2506 ret
= write_discarded_items_message(ctx
, "events", stream
,
2507 beginning_cs
, end_cs
, count
);
2514 int write_discarded_packets_message(struct details_write_ctx
*ctx
,
2515 const bt_message
*msg
)
2518 const bt_stream
*stream
= bt_message_discarded_packets_borrow_stream_const(
2520 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2521 const bt_clock_snapshot
*beginning_cs
= NULL
;
2522 const bt_clock_snapshot
*end_cs
= NULL
;
2525 if (!ctx
->details_comp
->cfg
.with_data
) {
2529 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
)) {
2531 bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
2534 bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
2538 if (bt_message_discarded_packets_get_count(msg
, &count
) !=
2539 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2540 count
= UINT64_C(-1);
2543 ret
= write_discarded_items_message(ctx
, "packets", stream
,
2544 beginning_cs
, end_cs
, count
);
2551 int write_packet_end_message(struct details_write_ctx
*ctx
,
2552 const bt_message
*msg
)
2555 const bt_packet
*packet
=
2556 bt_message_packet_end_borrow_packet_const(msg
);
2557 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
2558 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2560 if (!ctx
->details_comp
->cfg
.with_data
) {
2565 if (bt_stream_class_packets_have_end_default_clock_snapshot(sc
)) {
2567 bt_message_packet_end_borrow_default_clock_snapshot_const(
2571 /* Write follow tag for message */
2572 ret
= write_message_follow_tag(ctx
, stream
);
2577 write_obj_type_name(ctx
, "Packet end");
2585 int write_message_iterator_inactivity_message(struct details_write_ctx
*ctx
,
2586 const bt_message
*msg
)
2589 const bt_clock_snapshot
*cs
=
2590 bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const(
2594 write_time(ctx
, cs
);
2595 write_obj_type_name(ctx
, "Message iterator inactivity");
2597 if (ctx
->details_comp
->cfg
.compact
) {
2602 /* Write clock class properties */
2603 g_string_append(ctx
->str
, ":\n");
2606 write_prop_name(ctx
, "Clock class");
2607 g_string_append_c(ctx
->str
, ':');
2610 write_clock_class_prop_lines(ctx
,
2611 bt_clock_snapshot_borrow_clock_class_const(cs
));
2619 int details_write_message(struct details_comp
*details_comp
,
2620 const bt_message
*msg
)
2623 struct details_write_ctx ctx
= {
2624 .details_comp
= details_comp
,
2625 .str
= details_comp
->str
,
2629 /* Reset output buffer */
2630 g_string_assign(details_comp
->str
, "");
2632 switch (bt_message_get_type(msg
)) {
2633 case BT_MESSAGE_TYPE_EVENT
:
2634 ret
= write_event_message(&ctx
, msg
);
2636 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
:
2637 ret
= write_message_iterator_inactivity_message(&ctx
, msg
);
2639 case BT_MESSAGE_TYPE_STREAM_BEGINNING
:
2640 ret
= write_stream_beginning_message(&ctx
, msg
);
2642 case BT_MESSAGE_TYPE_STREAM_END
:
2643 ret
= write_stream_end_message(&ctx
, msg
);
2645 case BT_MESSAGE_TYPE_PACKET_BEGINNING
:
2646 ret
= write_packet_beginning_message(&ctx
, msg
);
2648 case BT_MESSAGE_TYPE_PACKET_END
:
2649 ret
= write_packet_end_message(&ctx
, msg
);
2651 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
2652 ret
= write_discarded_events_message(&ctx
, msg
);
2654 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
2655 ret
= write_discarded_packets_message(&ctx
, msg
);
2662 * If this component printed at least one character so far, and
2663 * we're not in compact mode, and there's something in the
2664 * output buffer for this message, then prepend a newline to the
2665 * output buffer to visually separate message blocks.
2667 if (details_comp
->printed_something
&& !details_comp
->cfg
.compact
&&
2668 details_comp
->str
->len
> 0) {
2669 /* TODO: Optimize this */
2670 g_string_prepend_c(details_comp
->str
, '\n');