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 #define BT_LOG_TAG "PLUGIN-TEXT-DETAILS-SINK-WRITE"
26 #include <babeltrace2/babeltrace.h>
28 #include "common/assert.h"
29 #include "common/common.h"
32 #include "obj-lifetime-mgmt.h"
36 const char *plural(uint64_t value
)
38 return value
== 1 ? "" : "s";
42 void incr_indent_by(struct details_write_ctx
*ctx
, unsigned int value
)
45 ctx
->indent_level
+= value
;
49 void incr_indent(struct details_write_ctx
*ctx
)
51 incr_indent_by(ctx
, 2);
55 void decr_indent_by(struct details_write_ctx
*ctx
, unsigned int value
)
58 BT_ASSERT(ctx
->indent_level
>= value
);
59 ctx
->indent_level
-= value
;
63 void decr_indent(struct details_write_ctx
*ctx
)
65 decr_indent_by(ctx
, 2);
69 void format_uint(char *buf
, uint64_t value
, unsigned int base
)
71 const char *spec
= "%" PRIu64
;
72 char *buf_start
= buf
;
73 unsigned int digits_per_group
= 3;
75 bool sep_digits
= true;
80 /* TODO: Support binary format */
96 * Do not insert digit separators for numbers
97 * under 10,000 as it looks weird.
107 sprintf(buf_start
, spec
, value
);
110 bt_common_sep_digits(buf_start
, digits_per_group
, sep
);
115 void format_int(char *buf
, int64_t value
, unsigned int base
)
117 const char *spec
= "%" PRIu64
;
118 char *buf_start
= buf
;
119 unsigned int digits_per_group
= 3;
121 bool sep_digits
= true;
122 uint64_t abs_value
= value
< 0 ? (uint64_t) -value
: (uint64_t) value
;
132 /* TODO: Support binary format */
134 strcpy(buf_start
, "0x");
136 digits_per_group
= 4;
141 strcpy(buf_start
, "0");
146 if (value
>= -9999 && value
<= 9999) {
148 * Do not insert digit separators for numbers
149 * over -10,000 and under 10,000 as it looks
160 sprintf(buf_start
, spec
, abs_value
);
163 bt_common_sep_digits(buf_start
, digits_per_group
, sep
);
168 void write_nl(struct details_write_ctx
*ctx
)
171 g_string_append_c(ctx
->str
, '\n');
175 void write_sp(struct details_write_ctx
*ctx
)
178 g_string_append_c(ctx
->str
, ' ');
182 void write_indent(struct details_write_ctx
*ctx
)
188 for (i
= 0; i
< ctx
->indent_level
; i
++) {
194 void write_compound_member_name(struct details_write_ctx
*ctx
, const char *name
)
197 g_string_append_printf(ctx
->str
, "%s%s%s:",
198 color_fg_cyan(ctx
), name
, color_reset(ctx
));
202 void write_array_index(struct details_write_ctx
*ctx
, uint64_t index
)
207 format_uint(buf
, index
, 10);
208 g_string_append_printf(ctx
->str
, "%s[%s]%s:",
209 color_fg_cyan(ctx
), buf
, color_reset(ctx
));
213 void write_obj_type_name(struct details_write_ctx
*ctx
, const char *name
)
215 g_string_append_printf(ctx
->str
, "%s%s%s%s",
216 color_fg_yellow(ctx
), color_bold(ctx
), name
, color_reset(ctx
));
220 void write_prop_name(struct details_write_ctx
*ctx
, const char *prop_name
)
222 g_string_append_printf(ctx
->str
, "%s%s%s",
223 color_fg_magenta(ctx
), prop_name
, color_reset(ctx
));
227 void write_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
229 g_string_append_printf(ctx
->str
, "%s%s%s",
230 color_bold(ctx
), value
, color_reset(ctx
));
234 void write_uint_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
236 write_str_prop_value(ctx
, value
);
240 void write_uint_prop_value(struct details_write_ctx
*ctx
, uint64_t value
)
244 format_uint(buf
, value
, 10);
245 write_uint_str_prop_value(ctx
, buf
);
249 void write_int_prop_value(struct details_write_ctx
*ctx
, int64_t value
)
253 format_int(buf
, value
, 10);
254 write_uint_str_prop_value(ctx
, buf
);
258 void write_float_prop_value(struct details_write_ctx
*ctx
, double value
)
260 g_string_append_printf(ctx
->str
, "%s%f%s",
261 color_bold(ctx
), value
, color_reset(ctx
));
265 void write_str_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
266 const char *prop_value
)
268 BT_ASSERT(prop_value
);
270 write_prop_name(ctx
, prop_name
);
271 g_string_append(ctx
->str
, ": ");
272 write_str_prop_value(ctx
, prop_value
);
277 void write_uint_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
281 write_prop_name(ctx
, prop_name
);
282 g_string_append(ctx
->str
, ": ");
283 write_uint_prop_value(ctx
, prop_value
);
288 void write_int_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
292 write_prop_name(ctx
, prop_name
);
293 g_string_append(ctx
->str
, ": ");
294 write_int_prop_value(ctx
, prop_value
);
299 void write_int_str_prop_value(struct details_write_ctx
*ctx
, const char *value
)
301 write_str_prop_value(ctx
, value
);
305 void write_bool_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
311 write_prop_name(ctx
, prop_name
);
312 g_string_append_printf(ctx
->str
, ": %s", color_bold(ctx
));
315 g_string_append(ctx
->str
, color_fg_green(ctx
));
318 g_string_append(ctx
->str
, color_fg_red(ctx
));
322 g_string_append_printf(ctx
->str
, "%s%s\n", str
, color_reset(ctx
));
326 void write_uuid_prop_line(struct details_write_ctx
*ctx
, const char *prop_name
,
331 write_prop_name(ctx
, prop_name
);
332 g_string_append_printf(ctx
->str
,
333 ": %s%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%s\n",
335 (unsigned int) uuid
[0],
336 (unsigned int) uuid
[1],
337 (unsigned int) uuid
[2],
338 (unsigned int) uuid
[3],
339 (unsigned int) uuid
[4],
340 (unsigned int) uuid
[5],
341 (unsigned int) uuid
[6],
342 (unsigned int) uuid
[7],
343 (unsigned int) uuid
[8],
344 (unsigned int) uuid
[9],
345 (unsigned int) uuid
[10],
346 (unsigned int) uuid
[11],
347 (unsigned int) uuid
[12],
348 (unsigned int) uuid
[13],
349 (unsigned int) uuid
[14],
350 (unsigned int) uuid
[15],
355 void write_int_field_class_props(struct details_write_ctx
*ctx
,
356 const bt_field_class
*fc
, bool close
)
358 g_string_append_printf(ctx
->str
, "(%s%" PRIu64
"-bit%s, Base ",
360 bt_field_class_integer_get_field_value_range(fc
),
363 switch (bt_field_class_integer_get_preferred_display_base(fc
)) {
364 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
365 write_uint_prop_value(ctx
, 2);
367 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
368 write_uint_prop_value(ctx
, 8);
370 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
371 write_uint_prop_value(ctx
, 10);
373 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
374 write_uint_prop_value(ctx
, 16);
381 g_string_append(ctx
->str
, ")");
385 struct enum_field_class_mapping_range
{
397 struct enum_field_class_mapping
{
401 /* Array of `struct enum_field_class_mapping_range` */
406 gint
compare_enum_field_class_mappings(struct enum_field_class_mapping
**a
,
407 struct enum_field_class_mapping
**b
)
409 return strcmp((*a
)->label
, (*b
)->label
);
413 gint
compare_enum_field_class_mapping_ranges_signed(
414 struct enum_field_class_mapping_range
*a
,
415 struct enum_field_class_mapping_range
*b
)
418 if (a
->lower
.i
< b
->lower
.i
) {
420 } else if (a
->lower
.i
> b
->lower
.i
) {
423 if (a
->upper
.i
< b
->upper
.i
) {
425 } else if (a
->upper
.i
> b
->upper
.i
) {
434 gint
compare_enum_field_class_mapping_ranges_unsigned(
435 struct enum_field_class_mapping_range
*a
,
436 struct enum_field_class_mapping_range
*b
)
438 if (a
->lower
.u
< b
->lower
.u
) {
440 } else if (a
->lower
.u
> b
->lower
.u
) {
443 if (a
->upper
.u
< b
->upper
.u
) {
445 } else if (a
->upper
.u
> b
->upper
.u
) {
454 void destroy_enum_field_class_mapping(struct enum_field_class_mapping
*mapping
)
456 if (mapping
->ranges
) {
457 g_array_free(mapping
->ranges
, TRUE
);
458 mapping
->ranges
= NULL
;
465 void write_enum_field_class_mapping_range(struct details_write_ctx
*ctx
,
466 struct enum_field_class_mapping_range
*range
, bool is_signed
)
468 g_string_append(ctx
->str
, "[");
471 write_int_prop_value(ctx
, range
->lower
.i
);
473 write_int_prop_value(ctx
, range
->lower
.u
);
476 g_string_append(ctx
->str
, ", ");
479 write_int_prop_value(ctx
, range
->upper
.i
);
481 write_int_prop_value(ctx
, range
->upper
.u
);
484 g_string_append(ctx
->str
, "]");
488 void write_enum_field_class_mappings(struct details_write_ctx
*ctx
,
489 const bt_field_class
*fc
)
494 bool is_signed
= bt_field_class_get_type(fc
) ==
495 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
;
497 mappings
= g_ptr_array_new_with_free_func(
498 (GDestroyNotify
) destroy_enum_field_class_mapping
);
502 * Copy field class's mappings to our own arrays and structures
505 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(fc
); i
++) {
506 const void *fc_mapping
;
507 struct enum_field_class_mapping
*mapping
= g_new0(
508 struct enum_field_class_mapping
, 1);
511 mapping
->ranges
= g_array_new(FALSE
, TRUE
,
512 sizeof(struct enum_field_class_mapping_range
));
513 BT_ASSERT(mapping
->ranges
);
516 fc_mapping
= bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
519 fc_mapping
= bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
523 mapping
->label
= bt_field_class_enumeration_mapping_get_label(
524 bt_field_class_signed_enumeration_mapping_as_mapping_const(
528 range_i
< bt_field_class_enumeration_mapping_get_range_count(
529 bt_field_class_signed_enumeration_mapping_as_mapping_const(fc_mapping
));
531 struct enum_field_class_mapping_range range
;
534 bt_field_class_signed_enumeration_mapping_get_range_by_index(
536 &range
.lower
.i
, &range
.upper
.i
);
538 bt_field_class_unsigned_enumeration_mapping_get_range_by_index(
540 &range
.lower
.u
, &range
.upper
.u
);
543 g_array_append_val(mapping
->ranges
, range
);
546 g_ptr_array_add(mappings
, mapping
);
549 /* Sort mappings, and for each mapping, sort ranges */
550 g_ptr_array_sort(mappings
,
551 (GCompareFunc
) compare_enum_field_class_mappings
);
553 for (i
= 0; i
< mappings
->len
; i
++) {
554 struct enum_field_class_mapping
*mapping
= mappings
->pdata
[i
];
557 g_array_sort(mapping
->ranges
,
559 compare_enum_field_class_mapping_ranges_signed
);
561 g_array_sort(mapping
->ranges
,
563 compare_enum_field_class_mapping_ranges_unsigned
);
568 for (i
= 0; i
< mappings
->len
; i
++) {
569 struct enum_field_class_mapping
*mapping
= mappings
->pdata
[i
];
572 write_compound_member_name(ctx
, mapping
->label
);
574 if (mapping
->ranges
->len
== 1) {
575 /* Single one: write on same line */
577 write_enum_field_class_mapping_range(ctx
,
578 &g_array_index(mapping
->ranges
,
579 struct enum_field_class_mapping_range
,
586 for (range_i
= 0; range_i
< mapping
->ranges
->len
; range_i
++) {
589 write_enum_field_class_mapping_range(ctx
,
590 &g_array_index(mapping
->ranges
,
591 struct enum_field_class_mapping_range
,
592 range_i
), is_signed
);
598 g_ptr_array_free(mappings
, TRUE
);
602 void write_field_path(struct details_write_ctx
*ctx
,
603 const bt_field_path
*field_path
)
607 g_string_append_c(ctx
->str
, '[');
609 switch (bt_field_path_get_root_scope(field_path
)) {
610 case BT_SCOPE_PACKET_CONTEXT
:
611 write_str_prop_value(ctx
, "Packet context");
613 case BT_SCOPE_EVENT_COMMON_CONTEXT
:
614 write_str_prop_value(ctx
, "Event common context");
616 case BT_SCOPE_EVENT_SPECIFIC_CONTEXT
:
617 write_str_prop_value(ctx
, "Event specific context");
619 case BT_SCOPE_EVENT_PAYLOAD
:
620 write_str_prop_value(ctx
, "Event payload");
626 g_string_append(ctx
->str
, ": ");
628 for (i
= 0; i
< bt_field_path_get_item_count(field_path
); i
++) {
629 const bt_field_path_item
*fp_item
=
630 bt_field_path_borrow_item_by_index_const(field_path
, i
);
633 g_string_append(ctx
->str
, ", ");
636 switch (bt_field_path_item_get_type(fp_item
)) {
637 case BT_FIELD_PATH_ITEM_TYPE_INDEX
:
638 write_uint_prop_value(ctx
,
639 bt_field_path_item_index_get_index(fp_item
));
641 case BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
:
642 write_str_prop_value(ctx
, "<current>");
649 g_string_append_c(ctx
->str
, ']');
653 void write_field_class(struct details_write_ctx
*ctx
, const bt_field_class
*fc
,
658 bt_field_class_type fc_type
= bt_field_class_get_type(fc
);
660 /* Write field class's name */
662 write_compound_member_name(ctx
, name
);
666 /* Write field class's type */
668 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
669 type
= "Unsigned integer";
671 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
672 type
= "Signed integer";
674 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
675 type
= "Unsigned enumeration";
677 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
678 type
= "Signed enumeration";
680 case BT_FIELD_CLASS_TYPE_REAL
:
683 case BT_FIELD_CLASS_TYPE_STRING
:
686 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
689 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
690 type
= "Static array";
692 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
693 type
= "Dynamic array";
695 case BT_FIELD_CLASS_TYPE_VARIANT
:
702 g_string_append_printf(ctx
->str
, "%s%s%s",
703 color_fg_blue(ctx
), type
, color_reset(ctx
));
705 /* Write field class's properties */
707 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
708 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
710 write_int_field_class_props(ctx
, fc
, true);
712 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
713 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
715 uint64_t mapping_count
=
716 bt_field_class_enumeration_get_mapping_count(fc
);
719 write_int_field_class_props(ctx
, fc
, false);
720 g_string_append(ctx
->str
, ", ");
721 write_uint_prop_value(ctx
, mapping_count
);
722 g_string_append_printf(ctx
->str
, " mapping%s)",
723 plural(mapping_count
));
725 if (mapping_count
> 0) {
726 g_string_append_c(ctx
->str
, ':');
728 write_enum_field_class_mappings(ctx
, fc
);
734 case BT_FIELD_CLASS_TYPE_REAL
:
735 if (bt_field_class_real_is_single_precision(fc
)) {
736 g_string_append(ctx
->str
, " (Single precision)");
738 g_string_append(ctx
->str
, " (Double precision)");
742 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
744 uint64_t member_count
=
745 bt_field_class_structure_get_member_count(fc
);
747 g_string_append(ctx
->str
, " (");
748 write_uint_prop_value(ctx
, member_count
);
749 g_string_append_printf(ctx
->str
, " member%s)",
750 plural(member_count
));
752 if (member_count
> 0) {
753 g_string_append_c(ctx
->str
, ':');
756 for (i
= 0; i
< member_count
; i
++) {
757 const bt_field_class_structure_member
*member
=
758 bt_field_class_structure_borrow_member_by_index_const(
762 write_field_class(ctx
,
763 bt_field_class_structure_member_borrow_field_class_const(member
),
764 bt_field_class_structure_member_get_name(member
));
772 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
773 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
774 if (fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
775 g_string_append(ctx
->str
, " (Length ");
776 write_uint_prop_value(ctx
,
777 bt_field_class_static_array_get_length(fc
));
778 g_string_append_c(ctx
->str
, ')');
780 const bt_field_path
*length_field_path
=
781 bt_field_class_dynamic_array_borrow_length_field_path_const(
784 if (length_field_path
) {
785 g_string_append(ctx
->str
, " (Length field path ");
786 write_field_path(ctx
, length_field_path
);
787 g_string_append_c(ctx
->str
, ')');
791 g_string_append_c(ctx
->str
, ':');
794 write_field_class(ctx
,
795 bt_field_class_array_borrow_element_field_class_const(fc
),
799 case BT_FIELD_CLASS_TYPE_VARIANT
:
801 uint64_t option_count
=
802 bt_field_class_variant_get_option_count(fc
);
803 const bt_field_path
*sel_field_path
=
804 bt_field_class_variant_borrow_selector_field_path_const(
807 g_string_append(ctx
->str
, " (");
808 write_uint_prop_value(ctx
, option_count
);
809 g_string_append_printf(ctx
->str
, " option%s, ",
810 plural(option_count
));
812 if (sel_field_path
) {
813 g_string_append(ctx
->str
, "Selector field path ");
814 write_field_path(ctx
, sel_field_path
);
817 g_string_append_c(ctx
->str
, ')');
819 if (option_count
> 0) {
820 g_string_append_c(ctx
->str
, ':');
823 for (i
= 0; i
< option_count
; i
++) {
824 const bt_field_class_variant_option
*option
=
825 bt_field_class_variant_borrow_option_by_index_const(
829 write_field_class(ctx
,
830 bt_field_class_variant_option_borrow_field_class_const(option
),
831 bt_field_class_variant_option_get_name(option
));
845 void write_root_field_class(struct details_write_ctx
*ctx
, const char *name
,
846 const bt_field_class
*fc
)
851 write_prop_name(ctx
, name
);
852 g_string_append(ctx
->str
, ": ");
853 write_field_class(ctx
, fc
, NULL
);
858 void write_event_class(struct details_write_ctx
*ctx
, const bt_event_class
*ec
)
860 const char *name
= bt_event_class_get_name(ec
);
862 const bt_field_class
*fc
;
863 bt_event_class_log_level log_level
;
866 write_obj_type_name(ctx
, "Event class");
868 /* Write name and ID */
870 g_string_append_printf(ctx
->str
, " `%s%s%s`",
871 color_fg_green(ctx
), name
, color_reset(ctx
));
874 g_string_append(ctx
->str
, " (ID ");
875 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
876 g_string_append(ctx
->str
, "):\n");
878 /* Write properties */
881 /* Write log level */
882 if (bt_event_class_get_log_level(ec
, &log_level
) ==
883 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
884 const char *ll_str
= NULL
;
887 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
:
888 ll_str
= "Emergency";
890 case BT_EVENT_CLASS_LOG_LEVEL_ALERT
:
893 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
:
896 case BT_EVENT_CLASS_LOG_LEVEL_ERROR
:
899 case BT_EVENT_CLASS_LOG_LEVEL_WARNING
:
902 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE
:
905 case BT_EVENT_CLASS_LOG_LEVEL_INFO
:
908 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
:
909 ll_str
= "Debug (system)";
911 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
:
912 ll_str
= "Debug (program)";
914 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
:
915 ll_str
= "Debug (process)";
917 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
:
918 ll_str
= "Debug (module)";
920 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
:
921 ll_str
= "Debug (unit)";
923 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
:
924 ll_str
= "Debug (function)";
926 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
:
927 ll_str
= "Debug (line)";
929 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG
:
936 write_str_prop_line(ctx
, "Log level", ll_str
);
940 emf_uri
= bt_event_class_get_emf_uri(ec
);
942 write_str_prop_line(ctx
, "EMF URI", emf_uri
);
945 /* Write specific context field class */
946 fc
= bt_event_class_borrow_specific_context_field_class_const(ec
);
948 write_root_field_class(ctx
, "Specific context field class", fc
);
951 /* Write payload field class */
952 fc
= bt_event_class_borrow_payload_field_class_const(ec
);
954 write_root_field_class(ctx
, "Payload field class", fc
);
961 void write_clock_class_prop_lines(struct details_write_ctx
*ctx
,
962 const bt_clock_class
*cc
)
964 int64_t offset_seconds
;
965 uint64_t offset_cycles
;
968 str
= bt_clock_class_get_name(cc
);
970 write_str_prop_line(ctx
, "Name", str
);
973 str
= bt_clock_class_get_description(cc
);
975 write_str_prop_line(ctx
, "Description", str
);
978 write_uint_prop_line(ctx
, "Frequency (Hz)",
979 bt_clock_class_get_frequency(cc
));
980 write_uint_prop_line(ctx
, "Precision (cycles)",
981 bt_clock_class_get_precision(cc
));
982 bt_clock_class_get_offset(cc
, &offset_seconds
, &offset_cycles
);
983 write_int_prop_line(ctx
, "Offset (s)", offset_seconds
);
984 write_uint_prop_line(ctx
, "Offset (cycles)", offset_cycles
);
985 write_bool_prop_line(ctx
, "Origin is Unix epoch",
986 bt_clock_class_origin_is_unix_epoch(cc
));
988 if (ctx
->details_comp
->cfg
.with_uuid
) {
989 bt_uuid uuid
= bt_clock_class_get_uuid(cc
);
992 write_uuid_prop_line(ctx
, "UUID", uuid
);
998 gint
compare_event_classes(const bt_event_class
**a
, const bt_event_class
**b
)
1000 uint64_t id_a
= bt_event_class_get_id(*a
);
1001 uint64_t id_b
= bt_event_class_get_id(*b
);
1005 } else if (id_a
> id_b
) {
1013 void write_stream_class(struct details_write_ctx
*ctx
,
1014 const bt_stream_class
*sc
)
1016 const bt_field_class
*fc
;
1017 GPtrArray
*event_classes
= g_ptr_array_new();
1021 write_obj_type_name(ctx
, "Stream class");
1023 /* Write name and ID */
1024 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
1025 const char *name
= bt_stream_class_get_name(sc
);
1028 g_string_append(ctx
->str
, " `");
1029 write_str_prop_value(ctx
, name
);
1030 g_string_append(ctx
->str
, "`");
1034 g_string_append(ctx
->str
, " (ID ");
1035 write_uint_prop_value(ctx
, bt_stream_class_get_id(sc
));
1036 g_string_append(ctx
->str
, "):\n");
1038 /* Write properties */
1041 /* Write configuration */
1042 write_bool_prop_line(ctx
,
1043 "Packets have beginning default clock snapshot",
1044 bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
));
1045 write_bool_prop_line(ctx
,
1046 "Packets have end default clock snapshot",
1047 bt_stream_class_packets_have_end_default_clock_snapshot(sc
));
1048 write_bool_prop_line(ctx
,
1049 "Supports discarded events",
1050 bt_stream_class_supports_discarded_events(sc
));
1051 write_bool_prop_line(ctx
,
1052 "Discarded events have default clock snapshots",
1053 bt_stream_class_discarded_events_have_default_clock_snapshots(sc
));
1054 write_bool_prop_line(ctx
,
1055 "Supports discarded packets",
1056 bt_stream_class_supports_discarded_packets(sc
));
1057 write_bool_prop_line(ctx
,
1058 "Discarded packets have default clock snapshots",
1059 bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
));
1061 /* Write default clock class */
1062 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
1064 write_prop_name(ctx
, "Default clock class");
1065 g_string_append_c(ctx
->str
, ':');
1068 write_clock_class_prop_lines(ctx
,
1069 bt_stream_class_borrow_default_clock_class_const(sc
));
1073 fc
= bt_stream_class_borrow_packet_context_field_class_const(sc
);
1075 write_root_field_class(ctx
, "Packet context field class", fc
);
1078 fc
= bt_stream_class_borrow_event_common_context_field_class_const(sc
);
1080 write_root_field_class(ctx
, "Event common context field class",
1084 for (i
= 0; i
< bt_stream_class_get_event_class_count(sc
); i
++) {
1085 g_ptr_array_add(event_classes
,
1086 (gpointer
) bt_stream_class_borrow_event_class_by_index_const(
1090 g_ptr_array_sort(event_classes
, (GCompareFunc
) compare_event_classes
);
1092 for (i
= 0; i
< event_classes
->len
; i
++) {
1093 write_event_class(ctx
, event_classes
->pdata
[i
]);
1097 g_ptr_array_free(event_classes
, TRUE
);
1101 gint
compare_stream_classes(const bt_stream_class
**a
, const bt_stream_class
**b
)
1103 uint64_t id_a
= bt_stream_class_get_id(*a
);
1104 uint64_t id_b
= bt_stream_class_get_id(*b
);
1108 } else if (id_a
> id_b
) {
1116 gint
compare_strings(const char **a
, const char **b
)
1118 return strcmp(*a
, *b
);
1122 void write_trace_class(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
)
1124 GPtrArray
*stream_classes
= g_ptr_array_new();
1125 GPtrArray
*env_names
= g_ptr_array_new();
1128 bool printed_prop
= false;
1131 write_obj_type_name(ctx
, "Trace class");
1134 if (ctx
->details_comp
->cfg
.with_trace_class_name
) {
1135 const char *name
= bt_trace_class_get_name(tc
);
1138 g_string_append(ctx
->str
, " `");
1139 write_str_prop_value(ctx
, name
);
1140 g_string_append(ctx
->str
, "`");
1144 /* Write properties */
1147 if (ctx
->details_comp
->cfg
.with_uuid
) {
1148 bt_uuid uuid
= bt_trace_class_get_uuid(tc
);
1151 if (!printed_prop
) {
1152 g_string_append(ctx
->str
, ":\n");
1153 printed_prop
= true;
1156 write_uuid_prop_line(ctx
, "UUID", uuid
);
1160 /* Write environment */
1161 env_count
= bt_trace_class_get_environment_entry_count(tc
);
1162 if (env_count
> 0) {
1163 if (!printed_prop
) {
1164 g_string_append(ctx
->str
, ":\n");
1165 printed_prop
= true;
1169 write_prop_name(ctx
, "Environment");
1170 g_string_append(ctx
->str
, " (");
1171 write_uint_prop_value(ctx
, env_count
);
1172 g_string_append_printf(ctx
->str
, " entr%s):",
1173 env_count
== 1 ? "y" : "ies");
1177 for (i
= 0; i
< env_count
; i
++) {
1179 const bt_value
*value
;
1181 bt_trace_class_borrow_environment_entry_by_index_const(
1182 tc
, i
, &name
, &value
);
1183 g_ptr_array_add(env_names
, (gpointer
) name
);
1186 g_ptr_array_sort(env_names
, (GCompareFunc
) compare_strings
);
1188 for (i
= 0; i
< env_names
->len
; i
++) {
1189 const char *name
= env_names
->pdata
[i
];
1190 const bt_value
*value
=
1191 bt_trace_class_borrow_environment_entry_value_by_name_const(
1195 write_compound_member_name(ctx
, name
);
1198 if (bt_value_get_type(value
) ==
1199 BT_VALUE_TYPE_SIGNED_INTEGER
) {
1200 write_int_prop_value(ctx
,
1201 bt_value_signed_integer_get(value
));
1202 } else if (bt_value_get_type(value
) ==
1203 BT_VALUE_TYPE_STRING
) {
1204 write_str_prop_value(ctx
,
1205 bt_value_string_get(value
));
1216 for (i
= 0; i
< bt_trace_class_get_stream_class_count(tc
); i
++) {
1217 g_ptr_array_add(stream_classes
,
1218 (gpointer
) bt_trace_class_borrow_stream_class_by_index_const(
1222 g_ptr_array_sort(stream_classes
, (GCompareFunc
) compare_stream_classes
);
1224 if (stream_classes
->len
> 0) {
1225 if (!printed_prop
) {
1226 g_string_append(ctx
->str
, ":\n");
1227 printed_prop
= true;
1231 for (i
= 0; i
< stream_classes
->len
; i
++) {
1232 write_stream_class(ctx
, stream_classes
->pdata
[i
]);
1237 if (!printed_prop
) {
1241 g_ptr_array_free(stream_classes
, TRUE
);
1242 g_ptr_array_free(env_names
, TRUE
);
1246 int try_write_meta(struct details_write_ctx
*ctx
, const bt_trace_class
*tc
,
1247 const bt_stream_class
*sc
, const bt_event_class
*ec
)
1253 if (details_need_to_write_trace_class(ctx
, tc
)) {
1256 if (ctx
->details_comp
->cfg
.compact
&&
1257 ctx
->details_comp
->printed_something
) {
1259 * There are no empty line between messages in
1260 * compact mode, so write one here to decouple
1261 * the trace class from the next message.
1267 * write_trace_class() also writes all its stream
1268 * classes their event classes, so we don't need to
1271 write_trace_class(ctx
, tc
);
1275 * Mark this trace class as written, as well as all
1276 * its stream classes and their event classes.
1278 ret
= details_did_write_trace_class(ctx
, tc
);
1283 for (sc_i
= 0; sc_i
< bt_trace_class_get_stream_class_count(tc
);
1286 const bt_stream_class
*tc_sc
=
1287 bt_trace_class_borrow_stream_class_by_index_const(
1290 details_did_write_meta_object(ctx
, tc
, tc_sc
);
1292 for (ec_i
= 0; ec_i
<
1293 bt_stream_class_get_event_class_count(tc_sc
);
1295 details_did_write_meta_object(ctx
, tc
,
1296 bt_stream_class_borrow_event_class_by_index_const(
1304 if (sc
&& details_need_to_write_meta_object(ctx
, tc
, sc
)) {
1309 if (ctx
->details_comp
->cfg
.compact
&&
1310 ctx
->details_comp
->printed_something
) {
1312 * There are no empty line between messages in
1313 * compact mode, so write one here to decouple
1314 * the stream class from the next message.
1320 * write_stream_class() also writes all its event
1321 * classes, so we don't need to rewrite `ec`.
1323 write_stream_class(ctx
, sc
);
1327 * Mark this stream class as written, as well as all its
1330 details_did_write_meta_object(ctx
, tc
, sc
);
1332 for (ec_i
= 0; ec_i
<
1333 bt_stream_class_get_event_class_count(sc
);
1335 details_did_write_meta_object(ctx
, tc
,
1336 bt_stream_class_borrow_event_class_by_index_const(
1343 if (ec
&& details_need_to_write_meta_object(ctx
, tc
, ec
)) {
1346 if (ctx
->details_comp
->cfg
.compact
&&
1347 ctx
->details_comp
->printed_something
) {
1349 * There are no empty line between messages in
1350 * compact mode, so write one here to decouple
1351 * the event class from the next message.
1356 write_event_class(ctx
, ec
);
1358 details_did_write_meta_object(ctx
, tc
, ec
);
1367 void write_time_str(struct details_write_ctx
*ctx
, const char *str
)
1369 if (!ctx
->details_comp
->cfg
.with_time
) {
1373 g_string_append_printf(ctx
->str
, "[%s%s%s%s]",
1374 color_bold(ctx
), color_fg_blue(ctx
), str
, color_reset(ctx
));
1376 if (ctx
->details_comp
->cfg
.compact
) {
1387 void write_time(struct details_write_ctx
*ctx
, const bt_clock_snapshot
*cs
)
1389 bt_clock_snapshot_status status
;
1390 int64_t ns_from_origin
;
1393 if (!ctx
->details_comp
->cfg
.with_time
) {
1397 format_uint(buf
, bt_clock_snapshot_get_value(cs
), 10);
1398 g_string_append_printf(ctx
->str
, "[%s%s%s%s%s",
1399 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1401 ctx
->details_comp
->cfg
.compact
? "" : " cycles");
1402 status
= bt_clock_snapshot_get_ns_from_origin(cs
, &ns_from_origin
);
1403 if (status
== BT_CLOCK_SNAPSHOT_STATUS_OK
) {
1404 format_int(buf
, ns_from_origin
, 10);
1405 g_string_append_printf(ctx
->str
, "%s %s%s%s%s%s",
1406 ctx
->details_comp
->cfg
.compact
? "" : ",",
1407 color_bold(ctx
), color_fg_blue(ctx
), buf
,
1409 ctx
->details_comp
->cfg
.compact
? "" : " ns from origin");
1412 g_string_append(ctx
->str
, "]");
1414 if (ctx
->details_comp
->cfg
.compact
) {
1425 int write_message_follow_tag(struct details_write_ctx
*ctx
,
1426 const bt_stream
*stream
)
1429 uint64_t unique_trace_id
;
1430 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1431 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
1433 ret
= details_trace_unique_id(ctx
, trace
, &unique_trace_id
);
1438 if (ctx
->details_comp
->cfg
.compact
) {
1439 g_string_append_printf(ctx
->str
,
1440 "%s{%s%" PRIu64
" %" PRIu64
" %" PRIu64
"%s%s}%s ",
1441 color_fg_cyan(ctx
), color_bold(ctx
),
1442 unique_trace_id
, bt_stream_class_get_id(sc
),
1443 bt_stream_get_id(stream
),
1444 color_reset(ctx
), color_fg_cyan(ctx
), color_reset(ctx
));
1446 g_string_append_printf(ctx
->str
,
1447 "%s{Trace %s%" PRIu64
"%s%s, Stream class ID %s%" PRIu64
"%s%s, Stream ID %s%" PRIu64
"%s%s}%s\n",
1449 color_bold(ctx
), unique_trace_id
,
1450 color_reset(ctx
), color_fg_cyan(ctx
),
1451 color_bold(ctx
), bt_stream_class_get_id(sc
),
1452 color_reset(ctx
), color_fg_cyan(ctx
),
1453 color_bold(ctx
), bt_stream_get_id(stream
),
1454 color_reset(ctx
), color_fg_cyan(ctx
),
1463 void write_field(struct details_write_ctx
*ctx
, const bt_field
*field
,
1467 bt_field_class_type fc_type
= bt_field_get_class_type(field
);
1468 const bt_field_class
*fc
;
1471 /* Write field's name */
1473 write_compound_member_name(ctx
, name
);
1476 /* Write field's value */
1478 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
1479 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
1480 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
1481 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
1483 unsigned int fmt_base
;
1484 bt_field_class_integer_preferred_display_base base
;
1486 fc
= bt_field_borrow_class_const(field
);
1487 base
= bt_field_class_integer_get_preferred_display_base(fc
);
1490 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
1493 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
1496 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
1499 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
1506 if (fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
1507 fc_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
1509 bt_field_unsigned_integer_get_value(field
),
1512 write_uint_str_prop_value(ctx
, buf
);
1515 bt_field_signed_integer_get_value(field
),
1518 write_int_str_prop_value(ctx
, buf
);
1523 case BT_FIELD_CLASS_TYPE_REAL
:
1525 write_float_prop_value(ctx
, bt_field_real_get_value(field
));
1527 case BT_FIELD_CLASS_TYPE_STRING
:
1529 write_str_prop_value(ctx
, bt_field_string_get_value(field
));
1531 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1533 uint64_t member_count
;
1535 fc
= bt_field_borrow_class_const(field
);
1536 member_count
= bt_field_class_structure_get_member_count(fc
);
1538 if (member_count
> 0) {
1541 for (i
= 0; i
< member_count
; i
++) {
1542 const bt_field_class_structure_member
*member
=
1543 bt_field_class_structure_borrow_member_by_index_const(
1545 const bt_field
*member_field
=
1546 bt_field_structure_borrow_member_field_by_index_const(
1550 write_field(ctx
, member_field
,
1551 bt_field_class_structure_member_get_name(member
));
1556 g_string_append(ctx
->str
, " Empty");
1561 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1562 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1564 uint64_t length
= bt_field_array_get_length(field
);
1567 g_string_append(ctx
->str
, " Empty");
1569 g_string_append(ctx
->str
, " Length ");
1570 write_uint_prop_value(ctx
, length
);
1571 g_string_append_c(ctx
->str
, ':');
1576 for (i
= 0; i
< length
; i
++) {
1577 const bt_field
*elem_field
=
1578 bt_field_array_borrow_element_field_by_index_const(
1582 write_array_index(ctx
, i
);
1583 write_field(ctx
, elem_field
, NULL
);
1589 case BT_FIELD_CLASS_TYPE_VARIANT
:
1591 bt_field_variant_borrow_selected_option_field_const(
1600 void write_root_field(struct details_write_ctx
*ctx
, const char *name
,
1601 const bt_field
*field
)
1606 write_prop_name(ctx
, name
);
1607 g_string_append(ctx
->str
, ":");
1608 write_field(ctx
, field
, NULL
);
1613 int write_event_message(struct details_write_ctx
*ctx
,
1614 const bt_message
*msg
)
1617 const bt_event
*event
= bt_message_event_borrow_event_const(msg
);
1618 const bt_stream
*stream
= bt_event_borrow_stream_const(event
);
1619 const bt_event_class
*ec
= bt_event_borrow_class_const(event
);
1620 const bt_stream_class
*sc
= bt_event_class_borrow_stream_class_const(ec
);
1621 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
1622 const char *ec_name
;
1623 const bt_field
*field
;
1625 ret
= try_write_meta(ctx
, tc
, sc
, ec
);
1631 if (bt_stream_class_borrow_default_clock_class_const(sc
)) {
1633 bt_message_event_borrow_default_clock_snapshot_const(
1637 /* Write follow tag for message */
1638 ret
= write_message_follow_tag(ctx
, stream
);
1643 /* Write object's basic properties */
1644 write_obj_type_name(ctx
, "Event");
1645 ec_name
= bt_event_class_get_name(ec
);
1647 g_string_append_printf(ctx
->str
, " `%s%s%s`",
1648 color_fg_green(ctx
), ec_name
, color_reset(ctx
));
1651 g_string_append(ctx
->str
, " (");
1653 if (!ctx
->details_comp
->cfg
.compact
) {
1654 g_string_append(ctx
->str
, "Class ID ");
1657 write_uint_prop_value(ctx
, bt_event_class_get_id(ec
));
1658 g_string_append(ctx
->str
, ")");
1660 if (ctx
->details_comp
->cfg
.compact
) {
1666 g_string_append(ctx
->str
, ":\n");
1668 field
= bt_event_borrow_common_context_field_const(event
);
1670 write_root_field(ctx
, "Common context", field
);
1673 field
= bt_event_borrow_specific_context_field_const(event
);
1675 write_root_field(ctx
, "Specific context", field
);
1678 field
= bt_event_borrow_payload_field_const(event
);
1680 write_root_field(ctx
, "Payload", field
);
1691 gint
compare_streams(const bt_stream
**a
, const bt_stream
**b
)
1693 uint64_t id_a
= bt_stream_get_id(*a
);
1694 uint64_t id_b
= bt_stream_get_id(*b
);
1698 } else if (id_a
> id_b
) {
1701 const bt_stream_class
*a_sc
= bt_stream_borrow_class_const(*a
);
1702 const bt_stream_class
*b_sc
= bt_stream_borrow_class_const(*b
);
1703 uint64_t a_sc_id
= bt_stream_class_get_id(a_sc
);
1704 uint64_t b_sc_id
= bt_stream_class_get_id(b_sc
);
1706 if (a_sc_id
< b_sc_id
) {
1708 } else if (a_sc_id
> b_sc_id
) {
1717 void write_trace(struct details_write_ctx
*ctx
, const bt_trace
*trace
)
1720 const bt_trace_class
*tc
= bt_trace_borrow_class_const(trace
);
1721 GPtrArray
*streams
= g_ptr_array_new();
1723 bool printed_prop
= false;
1726 write_obj_type_name(ctx
, "Trace");
1729 if (ctx
->details_comp
->cfg
.with_trace_name
) {
1730 name
= bt_trace_get_name(trace
);
1732 g_string_append(ctx
->str
, " `");
1733 write_str_prop_value(ctx
, name
);
1734 g_string_append(ctx
->str
, "`");
1738 /* Write properties */
1741 if (ctx
->details_comp
->cfg
.with_trace_class_name
) {
1742 name
= bt_trace_class_get_name(tc
);
1744 if (!printed_prop
) {
1745 g_string_append(ctx
->str
, ":\n");
1746 printed_prop
= true;
1749 write_str_prop_line(ctx
, "Class name", name
);
1753 if (ctx
->details_comp
->cfg
.with_uuid
) {
1754 bt_uuid uuid
= bt_trace_class_get_uuid(tc
);
1757 if (!printed_prop
) {
1758 g_string_append(ctx
->str
, ":\n");
1759 printed_prop
= true;
1762 write_uuid_prop_line(ctx
, "Class UUID", uuid
);
1766 for (i
= 0; i
< bt_trace_get_stream_count(trace
); i
++) {
1767 g_ptr_array_add(streams
,
1768 (gpointer
) bt_trace_borrow_stream_by_index_const(
1772 g_ptr_array_sort(streams
, (GCompareFunc
) compare_streams
);
1774 if (streams
->len
> 0 && !printed_prop
) {
1775 g_string_append(ctx
->str
, ":\n");
1776 printed_prop
= true;
1779 for (i
= 0; i
< streams
->len
; i
++) {
1780 const bt_stream
*stream
= streams
->pdata
[i
];
1783 write_obj_type_name(ctx
, "Stream");
1784 g_string_append(ctx
->str
, " (ID ");
1785 write_uint_prop_value(ctx
, bt_stream_get_id(stream
));
1786 g_string_append(ctx
->str
, ", Class ID ");
1787 write_uint_prop_value(ctx
, bt_stream_class_get_id(
1788 bt_stream_borrow_class_const(stream
)));
1789 g_string_append(ctx
->str
, ")");
1795 if (!printed_prop
) {
1799 g_ptr_array_free(streams
, TRUE
);
1803 int write_stream_beginning_message(struct details_write_ctx
*ctx
,
1804 const bt_message
*msg
)
1807 const bt_stream
*stream
=
1808 bt_message_stream_beginning_borrow_stream_const(msg
);
1809 const bt_trace
*trace
= bt_stream_borrow_trace_const(stream
);
1810 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1811 const bt_trace_class
*tc
= bt_stream_class_borrow_trace_class_const(sc
);
1814 ret
= try_write_meta(ctx
, tc
, sc
, NULL
);
1819 /* Write follow tag for message */
1820 ret
= write_message_follow_tag(ctx
, stream
);
1825 /* Write stream properties */
1826 write_obj_type_name(ctx
, "Stream beginning");
1828 if (ctx
->details_comp
->cfg
.compact
) {
1833 g_string_append(ctx
->str
, ":\n");
1836 if (ctx
->details_comp
->cfg
.with_stream_name
) {
1837 name
= bt_stream_get_name(stream
);
1839 write_str_prop_line(ctx
, "Name", name
);
1843 if (ctx
->details_comp
->cfg
.with_stream_class_name
) {
1844 name
= bt_stream_class_get_name(sc
);
1846 write_str_prop_line(ctx
, "Class name", name
);
1850 write_trace(ctx
, trace
);
1858 int write_stream_end_message(struct details_write_ctx
*ctx
,
1859 const bt_message
*msg
)
1862 const bt_stream
*stream
=
1863 bt_message_stream_end_borrow_stream_const(msg
);
1865 /* Write follow tag for message */
1866 ret
= write_message_follow_tag(ctx
, stream
);
1871 /* Write stream properties */
1872 write_obj_type_name(ctx
, "Stream end\n");
1879 int write_stream_activity_beginning_message(struct details_write_ctx
*ctx
,
1880 const bt_message
*msg
)
1883 const bt_stream
*stream
=
1884 bt_message_stream_activity_beginning_borrow_stream_const(msg
);
1885 bt_message_stream_activity_clock_snapshot_state cs_state
;
1886 const bt_clock_snapshot
*cs
= NULL
;
1889 cs_state
= bt_message_stream_activity_beginning_borrow_default_clock_snapshot_const(
1892 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN
:
1894 write_time(ctx
, cs
);
1896 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_UNKNOWN
:
1897 write_time_str(ctx
, "Unknown");
1899 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_INFINITE
:
1900 write_time_str(ctx
, "-Infinity");
1906 /* Write follow tag for message */
1907 ret
= write_message_follow_tag(ctx
, stream
);
1912 write_obj_type_name(ctx
, "Stream activity beginning");
1920 int write_stream_activity_end_message(struct details_write_ctx
*ctx
,
1921 const bt_message
*msg
)
1924 const bt_stream
*stream
=
1925 bt_message_stream_activity_end_borrow_stream_const(msg
);
1926 bt_message_stream_activity_clock_snapshot_state cs_state
;
1927 const bt_clock_snapshot
*cs
= NULL
;
1930 cs_state
= bt_message_stream_activity_end_borrow_default_clock_snapshot_const(
1933 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN
:
1935 write_time(ctx
, cs
);
1937 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_UNKNOWN
:
1938 write_time_str(ctx
, "Unknown");
1940 case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_INFINITE
:
1941 write_time_str(ctx
, "+Infinity");
1947 /* Write follow tag for message */
1948 ret
= write_message_follow_tag(ctx
, stream
);
1953 write_obj_type_name(ctx
, "Stream activity end");
1961 int write_packet_beginning_message(struct details_write_ctx
*ctx
,
1962 const bt_message
*msg
)
1965 const bt_packet
*packet
=
1966 bt_message_packet_beginning_borrow_packet_const(msg
);
1967 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
1968 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
1969 const bt_field
*field
;
1972 if (bt_stream_class_packets_have_beginning_default_clock_snapshot(sc
)) {
1974 bt_message_packet_beginning_borrow_default_clock_snapshot_const(
1978 /* Write follow tag for message */
1979 ret
= write_message_follow_tag(ctx
, stream
);
1984 write_obj_type_name(ctx
, "Packet beginning");
1986 if (ctx
->details_comp
->cfg
.compact
) {
1992 g_string_append(ctx
->str
, ":\n");
1994 field
= bt_packet_borrow_context_field_const(packet
);
1996 write_root_field(ctx
, "Context", field
);
2006 int write_discarded_items_message(struct details_write_ctx
*ctx
,
2007 const char *name
, const bt_stream
*stream
,
2008 const bt_clock_snapshot
*beginning_cs
,
2009 const bt_clock_snapshot
*end_cs
, uint64_t count
)
2015 write_time(ctx
, beginning_cs
);
2017 write_time(ctx
, end_cs
);
2020 /* Write follow tag for message */
2021 ret
= write_message_follow_tag(ctx
, stream
);
2026 write_obj_type_name(ctx
, "Discarded ");
2027 write_obj_type_name(ctx
, name
);
2030 if (count
== UINT64_C(-1)) {
2035 g_string_append(ctx
->str
, " (");
2036 write_uint_prop_value(ctx
, count
);
2037 g_string_append_printf(ctx
->str
, " %s)\n", name
);
2044 int write_discarded_events_message(struct details_write_ctx
*ctx
,
2045 const bt_message
*msg
)
2047 const bt_stream
*stream
= bt_message_discarded_events_borrow_stream_const(
2049 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2050 const bt_clock_snapshot
*beginning_cs
= NULL
;
2051 const bt_clock_snapshot
*end_cs
= NULL
;
2054 if (bt_stream_class_discarded_events_have_default_clock_snapshots(sc
)) {
2056 bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
2059 bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
2063 if (bt_message_discarded_events_get_count(msg
, &count
) !=
2064 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2065 count
= UINT64_C(-1);
2068 return write_discarded_items_message(ctx
, "events", stream
,
2069 beginning_cs
, end_cs
, count
);
2073 int write_discarded_packets_message(struct details_write_ctx
*ctx
,
2074 const bt_message
*msg
)
2076 const bt_stream
*stream
= bt_message_discarded_packets_borrow_stream_const(
2078 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2079 const bt_clock_snapshot
*beginning_cs
= NULL
;
2080 const bt_clock_snapshot
*end_cs
= NULL
;
2083 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(sc
)) {
2085 bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
2088 bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
2092 if (bt_message_discarded_packets_get_count(msg
, &count
) !=
2093 BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
2094 count
= UINT64_C(-1);
2097 return write_discarded_items_message(ctx
, "packets", stream
,
2098 beginning_cs
, end_cs
, count
);
2102 int write_packet_end_message(struct details_write_ctx
*ctx
,
2103 const bt_message
*msg
)
2106 const bt_packet
*packet
=
2107 bt_message_packet_end_borrow_packet_const(msg
);
2108 const bt_stream
*stream
= bt_packet_borrow_stream_const(packet
);
2109 const bt_stream_class
*sc
= bt_stream_borrow_class_const(stream
);
2112 if (bt_stream_class_packets_have_end_default_clock_snapshot(sc
)) {
2114 bt_message_packet_end_borrow_default_clock_snapshot_const(
2118 /* Write follow tag for message */
2119 ret
= write_message_follow_tag(ctx
, stream
);
2124 write_obj_type_name(ctx
, "Packet end");
2132 int write_message_iterator_inactivity_message(struct details_write_ctx
*ctx
,
2133 const bt_message
*msg
)
2136 const bt_clock_snapshot
*cs
=
2137 bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const(
2141 write_time(ctx
, cs
);
2142 write_obj_type_name(ctx
, "Message iterator inactivity");
2144 if (ctx
->details_comp
->cfg
.compact
) {
2149 /* Write clock class properties */
2150 g_string_append(ctx
->str
, ":\n");
2153 write_prop_name(ctx
, "Clock class");
2154 g_string_append_c(ctx
->str
, ':');
2157 write_clock_class_prop_lines(ctx
,
2158 bt_clock_snapshot_borrow_clock_class_const(cs
));
2166 int details_write_message(struct details_comp
*details_comp
,
2167 const bt_message
*msg
)
2170 struct details_write_ctx ctx
= {
2171 .details_comp
= details_comp
,
2172 .str
= details_comp
->str
,
2176 /* Reset output buffer */
2177 g_string_assign(details_comp
->str
, "");
2179 if (details_comp
->printed_something
&& !details_comp
->cfg
.compact
) {
2183 switch (bt_message_get_type(msg
)) {
2184 case BT_MESSAGE_TYPE_EVENT
:
2185 ret
= write_event_message(&ctx
, msg
);
2187 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
:
2188 ret
= write_message_iterator_inactivity_message(&ctx
, msg
);
2190 case BT_MESSAGE_TYPE_STREAM_BEGINNING
:
2191 ret
= write_stream_beginning_message(&ctx
, msg
);
2193 case BT_MESSAGE_TYPE_STREAM_END
:
2194 ret
= write_stream_end_message(&ctx
, msg
);
2196 case BT_MESSAGE_TYPE_PACKET_BEGINNING
:
2197 ret
= write_packet_beginning_message(&ctx
, msg
);
2199 case BT_MESSAGE_TYPE_PACKET_END
:
2200 ret
= write_packet_end_message(&ctx
, msg
);
2202 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_BEGINNING
:
2203 ret
= write_stream_activity_beginning_message(&ctx
, msg
);
2205 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_END
:
2206 ret
= write_stream_activity_end_message(&ctx
, msg
);
2208 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
2209 ret
= write_discarded_events_message(&ctx
, msg
);
2211 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
2212 ret
= write_discarded_packets_message(&ctx
, msg
);