flt.lttng-utils.debug-info: copy user attributes
[babeltrace.git] / src / plugins / text / details / write.c
CommitLineData
55478183
PP
1/*
2 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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
20 * SOFTWARE.
21 */
22
55478183 23#include <babeltrace2/babeltrace.h>
350ad6c1
PP
24#include <stdio.h>
25#include <string.h>
55478183
PP
26
27#include "common/assert.h"
28#include "common/common.h"
6162e6b7 29#include "common/uuid.h"
55478183
PP
30#include "details.h"
31#include "write.h"
32#include "obj-lifetime-mgmt.h"
33#include "colors.h"
34
35static inline
36const char *plural(uint64_t value)
37{
38 return value == 1 ? "" : "s";
39}
40
41static inline
42void incr_indent_by(struct details_write_ctx *ctx, unsigned int value)
43{
44 BT_ASSERT(ctx);
45 ctx->indent_level += value;
46}
47
48static inline
49void incr_indent(struct details_write_ctx *ctx)
50{
51 incr_indent_by(ctx, 2);
52}
53
54static inline
55void decr_indent_by(struct details_write_ctx *ctx, unsigned int value)
56{
57 BT_ASSERT(ctx);
58 BT_ASSERT(ctx->indent_level >= value);
59 ctx->indent_level -= value;
60}
61
62static inline
63void decr_indent(struct details_write_ctx *ctx)
64{
65 decr_indent_by(ctx, 2);
66}
67
68static inline
69void format_uint(char *buf, uint64_t value, unsigned int base)
70{
71 const char *spec = "%" PRIu64;
72 char *buf_start = buf;
73 unsigned int digits_per_group = 3;
74 char sep = ',';
75 bool sep_digits = true;
76
77 switch (base) {
78 case 2:
79 case 16:
80 /* TODO: Support binary format */
81 spec = "%" PRIx64;
82 strcpy(buf, "0x");
83 buf_start = buf + 2;
84 digits_per_group = 4;
85 sep = ':';
86 break;
87 case 8:
88 spec = "%" PRIo64;
89 strcpy(buf, "0");
90 buf_start = buf + 1;
91 sep = ':';
92 break;
93 case 10:
94 if (value <= 9999) {
95 /*
96 * Do not insert digit separators for numbers
97 * under 10,000 as it looks weird.
98 */
99 sep_digits = false;
100 }
101
102 break;
103 default:
104 abort();
105 }
106
107 sprintf(buf_start, spec, value);
108
109 if (sep_digits) {
110 bt_common_sep_digits(buf_start, digits_per_group, sep);
111 }
112}
113
114static inline
115void format_int(char *buf, int64_t value, unsigned int base)
116{
117 const char *spec = "%" PRIu64;
118 char *buf_start = buf;
119 unsigned int digits_per_group = 3;
120 char sep = ',';
121 bool sep_digits = true;
122 uint64_t abs_value = value < 0 ? (uint64_t) -value : (uint64_t) value;
123
124 if (value < 0) {
125 buf[0] = '-';
126 buf_start++;
127 }
128
129 switch (base) {
130 case 2:
131 case 16:
132 /* TODO: Support binary format */
133 spec = "%" PRIx64;
134 strcpy(buf_start, "0x");
135 buf_start += 2;
136 digits_per_group = 4;
137 sep = ':';
138 break;
139 case 8:
140 spec = "%" PRIo64;
141 strcpy(buf_start, "0");
142 buf_start++;
143 sep = ':';
144 break;
145 case 10:
146 if (value >= -9999 && value <= 9999) {
147 /*
148 * Do not insert digit separators for numbers
149 * over -10,000 and under 10,000 as it looks
150 * weird.
151 */
152 sep_digits = false;
153 }
154
155 break;
156 default:
157 abort();
158 }
159
160 sprintf(buf_start, spec, abs_value);
161
162 if (sep_digits) {
163 bt_common_sep_digits(buf_start, digits_per_group, sep);
164 }
165}
166
167static inline
168void write_nl(struct details_write_ctx *ctx)
169{
170 BT_ASSERT(ctx);
171 g_string_append_c(ctx->str, '\n');
172}
173
174static inline
175void write_sp(struct details_write_ctx *ctx)
176{
177 BT_ASSERT(ctx);
178 g_string_append_c(ctx->str, ' ');
179}
180
181static inline
182void write_indent(struct details_write_ctx *ctx)
183{
184 uint64_t i;
185
186 BT_ASSERT(ctx);
187
188 for (i = 0; i < ctx->indent_level; i++) {
189 write_sp(ctx);
190 }
191}
192
193static inline
194void write_compound_member_name(struct details_write_ctx *ctx, const char *name)
195{
196 write_indent(ctx);
197 g_string_append_printf(ctx->str, "%s%s%s:",
198 color_fg_cyan(ctx), name, color_reset(ctx));
199}
200
201static inline
202void write_array_index(struct details_write_ctx *ctx, uint64_t index)
203{
204 char buf[32];
205
206 write_indent(ctx);
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));
210}
211
212static inline
213void write_obj_type_name(struct details_write_ctx *ctx, const char *name)
214{
215 g_string_append_printf(ctx->str, "%s%s%s%s",
216 color_fg_yellow(ctx), color_bold(ctx), name, color_reset(ctx));
217}
218
219static inline
220void write_prop_name(struct details_write_ctx *ctx, const char *prop_name)
221{
222 g_string_append_printf(ctx->str, "%s%s%s",
223 color_fg_magenta(ctx), prop_name, color_reset(ctx));
224}
225
226static inline
227void write_str_prop_value(struct details_write_ctx *ctx, const char *value)
228{
229 g_string_append_printf(ctx->str, "%s%s%s",
230 color_bold(ctx), value, color_reset(ctx));
231}
232
25510d56
PP
233static inline
234void write_none_prop_value(struct details_write_ctx *ctx, const char *value)
235{
236 g_string_append_printf(ctx->str, "%s%s%s%s",
237 color_bold(ctx), color_fg_magenta(ctx),
238 value, color_reset(ctx));
239}
240
55478183
PP
241static inline
242void write_uint_str_prop_value(struct details_write_ctx *ctx, const char *value)
243{
244 write_str_prop_value(ctx, value);
245}
246
247static inline
248void write_uint_prop_value(struct details_write_ctx *ctx, uint64_t value)
249{
250 char buf[32];
251
252 format_uint(buf, value, 10);
253 write_uint_str_prop_value(ctx, buf);
254}
255
256static inline
257void write_int_prop_value(struct details_write_ctx *ctx, int64_t value)
258{
259 char buf[32];
260
261 format_int(buf, value, 10);
262 write_uint_str_prop_value(ctx, buf);
263}
264
265static inline
266void write_float_prop_value(struct details_write_ctx *ctx, double value)
267{
268 g_string_append_printf(ctx->str, "%s%f%s",
269 color_bold(ctx), value, color_reset(ctx));
270}
271
272static inline
273void write_str_prop_line(struct details_write_ctx *ctx, const char *prop_name,
274 const char *prop_value)
275{
276 BT_ASSERT(prop_value);
277 write_indent(ctx);
278 write_prop_name(ctx, prop_name);
279 g_string_append(ctx->str, ": ");
280 write_str_prop_value(ctx, prop_value);
281 write_nl(ctx);
282}
283
284static inline
285void write_uint_prop_line(struct details_write_ctx *ctx, const char *prop_name,
286 uint64_t prop_value)
287{
288 write_indent(ctx);
289 write_prop_name(ctx, prop_name);
290 g_string_append(ctx->str, ": ");
291 write_uint_prop_value(ctx, prop_value);
292 write_nl(ctx);
293}
294
295static inline
296void write_int_prop_line(struct details_write_ctx *ctx, const char *prop_name,
297 int64_t prop_value)
298{
299 write_indent(ctx);
300 write_prop_name(ctx, prop_name);
301 g_string_append(ctx->str, ": ");
302 write_int_prop_value(ctx, prop_value);
303 write_nl(ctx);
304}
305
306static inline
307void write_int_str_prop_value(struct details_write_ctx *ctx, const char *value)
308{
309 write_str_prop_value(ctx, value);
310}
311
312static inline
dacaa55d 313void write_bool_prop_value(struct details_write_ctx *ctx, bt_bool prop_value)
55478183
PP
314{
315 const char *str;
316
dacaa55d 317 g_string_append(ctx->str, color_bold(ctx));
55478183
PP
318
319 if (prop_value) {
320 g_string_append(ctx->str, color_fg_green(ctx));
321 str = "Yes";
322 } else {
323 g_string_append(ctx->str, color_fg_red(ctx));
324 str = "No";
325 }
326
dacaa55d
PP
327 g_string_append_printf(ctx->str, "%s%s", str, color_reset(ctx));
328}
329
330static inline
331void write_bool_prop_line(struct details_write_ctx *ctx, const char *prop_name,
332 bt_bool prop_value)
333{
334 write_indent(ctx);
335 write_prop_name(ctx, prop_name);
336 g_string_append(ctx->str, ": ");
337 write_bool_prop_value(ctx, prop_value);
338 write_nl(ctx);
55478183
PP
339}
340
341static inline
342void write_uuid_prop_line(struct details_write_ctx *ctx, const char *prop_name,
343 bt_uuid uuid)
344{
345 BT_ASSERT(uuid);
346 write_indent(ctx);
347 write_prop_name(ctx, prop_name);
348 g_string_append_printf(ctx->str,
6162e6b7 349 ": %s" BT_UUID_FMT "%s\n",
55478183 350 color_bold(ctx),
6162e6b7 351 BT_UUID_FMT_VALUES(uuid),
55478183
PP
352 color_reset(ctx));
353}
354
355static
356void write_int_field_class_props(struct details_write_ctx *ctx,
357 const bt_field_class *fc, bool close)
358{
359 g_string_append_printf(ctx->str, "(%s%" PRIu64 "-bit%s, Base ",
360 color_bold(ctx),
361 bt_field_class_integer_get_field_value_range(fc),
362 color_reset(ctx));
363
364 switch (bt_field_class_integer_get_preferred_display_base(fc)) {
365 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY:
366 write_uint_prop_value(ctx, 2);
367 break;
368 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL:
369 write_uint_prop_value(ctx, 8);
370 break;
371 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL:
372 write_uint_prop_value(ctx, 10);
373 break;
374 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL:
375 write_uint_prop_value(ctx, 16);
376 break;
377 default:
378 abort();
379 }
380
381 if (close) {
382 g_string_append(ctx->str, ")");
383 }
384}
385
45c51519 386struct int_range {
55478183
PP
387 union {
388 uint64_t u;
389 int64_t i;
390 } lower;
391
392 union {
393 uint64_t u;
394 int64_t i;
395 } upper;
396};
397
398struct enum_field_class_mapping {
399 /* Weak */
400 const char *label;
401
45c51519 402 /* Array of `struct int_range` */
55478183
PP
403 GArray *ranges;
404};
405
406static
407gint compare_enum_field_class_mappings(struct enum_field_class_mapping **a,
408 struct enum_field_class_mapping **b)
409{
410 return strcmp((*a)->label, (*b)->label);
411}
412
413static
45c51519 414gint compare_int_ranges_signed(struct int_range *a, struct int_range *b)
55478183
PP
415{
416
417 if (a->lower.i < b->lower.i) {
418 return -1;
419 } else if (a->lower.i > b->lower.i) {
420 return 1;
421 } else {
422 if (a->upper.i < b->upper.i) {
423 return -1;
424 } else if (a->upper.i > b->upper.i) {
425 return 1;
426 } else {
427 return 0;
428 }
429 }
430}
431
432static
45c51519 433gint compare_int_ranges_unsigned(struct int_range *a, struct int_range *b)
55478183
PP
434{
435 if (a->lower.u < b->lower.u) {
436 return -1;
437 } else if (a->lower.u > b->lower.u) {
438 return 1;
439 } else {
440 if (a->upper.u < b->upper.u) {
441 return -1;
442 } else if (a->upper.u > b->upper.u) {
443 return 1;
444 } else {
445 return 0;
446 }
447 }
448}
449
45c51519
PP
450static
451GArray *range_set_to_int_ranges(const void *spec_range_set, bool is_signed)
452{
453 uint64_t i;
454 const bt_integer_range_set *range_set;
455 GArray *ranges = g_array_new(FALSE, TRUE, sizeof(struct int_range));
456
457 if (!ranges) {
458 goto end;
459 }
460
461 if (is_signed) {
462 range_set = bt_integer_range_set_signed_as_range_set_const(
463 spec_range_set);
464 } else {
465 range_set = bt_integer_range_set_unsigned_as_range_set_const(
466 spec_range_set);
467 }
468
469 for (i = 0; i < bt_integer_range_set_get_range_count(range_set); i++) {
470 struct int_range range;
471
472 if (is_signed) {
473 const bt_integer_range_signed *orig_range =
474 bt_integer_range_set_signed_borrow_range_by_index_const(
475 spec_range_set, i);
476
477 range.lower.i = bt_integer_range_signed_get_lower(orig_range);
478 range.upper.i = bt_integer_range_signed_get_upper(orig_range);
479 } else {
480 const bt_integer_range_unsigned *orig_range =
481 bt_integer_range_set_unsigned_borrow_range_by_index_const(
482 spec_range_set, i);
483
484 range.lower.u = bt_integer_range_unsigned_get_lower(orig_range);
485 range.upper.u = bt_integer_range_unsigned_get_upper(orig_range);
486 }
487
488 g_array_append_val(ranges, range);
489 }
490
491 if (is_signed) {
492 g_array_sort(ranges, (GCompareFunc) compare_int_ranges_signed);
493 } else {
494 g_array_sort(ranges,
495 (GCompareFunc) compare_int_ranges_unsigned);
496 }
497
498end:
499 return ranges;
500}
501
55478183
PP
502static
503void destroy_enum_field_class_mapping(struct enum_field_class_mapping *mapping)
504{
505 if (mapping->ranges) {
506 g_array_free(mapping->ranges, TRUE);
507 mapping->ranges = NULL;
508 }
509
510 g_free(mapping);
511}
512
513static
45c51519
PP
514struct int_range *int_range_at(GArray *ranges, uint64_t index)
515{
516 return &g_array_index(ranges, struct int_range, index);
517}
518
519static
520void write_int_range(struct details_write_ctx *ctx,
521 struct int_range *range, bool is_signed)
55478183
PP
522{
523 g_string_append(ctx->str, "[");
524
525 if (is_signed) {
526 write_int_prop_value(ctx, range->lower.i);
527 } else {
528 write_int_prop_value(ctx, range->lower.u);
529 }
530
45c51519
PP
531 if (range->lower.u != range->upper.u) {
532 g_string_append(ctx->str, ", ");
55478183 533
45c51519
PP
534 if (is_signed) {
535 write_int_prop_value(ctx, range->upper.i);
536 } else {
537 write_int_prop_value(ctx, range->upper.u);
538 }
55478183
PP
539 }
540
541 g_string_append(ctx->str, "]");
542}
543
544static
545void write_enum_field_class_mappings(struct details_write_ctx *ctx,
546 const bt_field_class *fc)
547{
548 GPtrArray *mappings;
549 uint64_t i;
550 uint64_t range_i;
551 bool is_signed = bt_field_class_get_type(fc) ==
552 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION;
553
554 mappings = g_ptr_array_new_with_free_func(
555 (GDestroyNotify) destroy_enum_field_class_mapping);
556 BT_ASSERT(mappings);
557
558 /*
559 * Copy field class's mappings to our own arrays and structures
560 * to sort them.
561 */
562 for (i = 0; i < bt_field_class_enumeration_get_mapping_count(fc); i++) {
563 const void *fc_mapping;
45c51519 564 const void *fc_range_set;
55478183
PP
565 struct enum_field_class_mapping *mapping = g_new0(
566 struct enum_field_class_mapping, 1);
567
568 BT_ASSERT(mapping);
55478183
PP
569
570 if (is_signed) {
9c08c816 571 fc_mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
55478183 572 fc, i);
9c08c816 573 fc_range_set = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
45c51519 574 fc_mapping);
55478183 575 } else {
9c08c816 576 fc_mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
55478183 577 fc, i);
9c08c816 578 fc_range_set = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
45c51519 579 fc_mapping);
55478183
PP
580 }
581
582 mapping->label = bt_field_class_enumeration_mapping_get_label(
9c08c816 583 bt_field_class_enumeration_signed_mapping_as_mapping_const(
55478183 584 fc_mapping));
45c51519
PP
585 mapping->ranges = range_set_to_int_ranges(fc_range_set,
586 is_signed);
587 BT_ASSERT(mapping->ranges);
55478183
PP
588 g_ptr_array_add(mappings, mapping);
589 }
590
45c51519 591 /* Sort mappings (ranges are already sorted within mappings) */
55478183
PP
592 g_ptr_array_sort(mappings,
593 (GCompareFunc) compare_enum_field_class_mappings);
594
55478183
PP
595 /* Write mappings */
596 for (i = 0; i < mappings->len; i++) {
597 struct enum_field_class_mapping *mapping = mappings->pdata[i];
598
599 write_nl(ctx);
600 write_compound_member_name(ctx, mapping->label);
601
55478183 602 for (range_i = 0; range_i < mapping->ranges->len; range_i++) {
45c51519
PP
603 write_sp(ctx);
604 write_int_range(ctx,
605 int_range_at(mapping->ranges, range_i),
606 is_signed);
55478183 607 }
55478183
PP
608 }
609
610 g_ptr_array_free(mappings, TRUE);
611}
612
613static
614void write_field_path(struct details_write_ctx *ctx,
615 const bt_field_path *field_path)
616{
617 uint64_t i;
618
619 g_string_append_c(ctx->str, '[');
620
621 switch (bt_field_path_get_root_scope(field_path)) {
e7ceb9df 622 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT:
55478183
PP
623 write_str_prop_value(ctx, "Packet context");
624 break;
e7ceb9df 625 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT:
55478183
PP
626 write_str_prop_value(ctx, "Event common context");
627 break;
e7ceb9df 628 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT:
55478183
PP
629 write_str_prop_value(ctx, "Event specific context");
630 break;
e7ceb9df 631 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD:
55478183
PP
632 write_str_prop_value(ctx, "Event payload");
633 break;
634 default:
635 abort();
636 }
637
638 g_string_append(ctx->str, ": ");
639
640 for (i = 0; i < bt_field_path_get_item_count(field_path); i++) {
641 const bt_field_path_item *fp_item =
642 bt_field_path_borrow_item_by_index_const(field_path, i);
643
644 if (i != 0) {
645 g_string_append(ctx->str, ", ");
646 }
647
648 switch (bt_field_path_item_get_type(fp_item)) {
649 case BT_FIELD_PATH_ITEM_TYPE_INDEX:
650 write_uint_prop_value(ctx,
651 bt_field_path_item_index_get_index(fp_item));
652 break;
653 case BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT:
654 write_str_prop_value(ctx, "<current>");
655 break;
656 default:
657 abort();
658 }
659 }
660
661 g_string_append_c(ctx->str, ']');
662}
663
664static
45c51519
PP
665void write_field_class(struct details_write_ctx *ctx, const bt_field_class *fc);
666
667static
668void write_variant_field_class_option(struct details_write_ctx *ctx,
669 const bt_field_class *fc, uint64_t index)
55478183 670{
55478183 671 bt_field_class_type fc_type = bt_field_class_get_type(fc);
45c51519
PP
672 const bt_field_class_variant_option *option =
673 bt_field_class_variant_borrow_option_by_index_const(
674 fc, index);
675 const void *orig_ranges;
676 GArray *int_ranges = NULL;
677 bool is_signed;
55478183 678
45c51519
PP
679 write_nl(ctx);
680 write_compound_member_name(ctx,
681 bt_field_class_variant_option_get_name(option));
682
683 if (fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR) {
9c08c816
PP
684 const bt_field_class_variant_with_selector_unsigned_option *spec_opt =
685 bt_field_class_variant_with_selector_unsigned_borrow_option_by_index_const(
45c51519
PP
686 fc, index);
687
688 orig_ranges =
9c08c816 689 bt_field_class_variant_with_selector_unsigned_option_borrow_ranges_const(
45c51519
PP
690 spec_opt);
691 is_signed = false;
692 } else {
9c08c816
PP
693 const bt_field_class_variant_with_selector_signed_option *spec_opt =
694 bt_field_class_variant_with_selector_signed_borrow_option_by_index_const(
45c51519
PP
695 fc, index);
696
697 orig_ranges =
9c08c816 698 bt_field_class_variant_with_selector_signed_option_borrow_ranges_const(
45c51519
PP
699 spec_opt);
700 is_signed = true;
701 }
702
703 if (orig_ranges) {
704 uint64_t i;
705
706 int_ranges = range_set_to_int_ranges(orig_ranges, is_signed);
707 BT_ASSERT(int_ranges);
708
709 for (i = 0; i < int_ranges->len; i++) {
710 struct int_range *range = int_range_at(int_ranges, i);
711
712 write_sp(ctx);
713 write_int_range(ctx, range, is_signed);
714 }
715
716 g_string_append(ctx->str, ": ");
717 } else {
55478183
PP
718 write_sp(ctx);
719 }
720
45c51519
PP
721 write_field_class(ctx,
722 bt_field_class_variant_option_borrow_field_class_const(option));
723
724 if (int_ranges) {
725 g_array_free(int_ranges, TRUE);
726 }
727}
728
729static
730void write_variant_field_class(struct details_write_ctx *ctx,
731 const bt_field_class *fc)
732{
733 bt_field_class_type fc_type = bt_field_class_get_type(fc);
734 uint64_t option_count =
735 bt_field_class_variant_get_option_count(fc);
736 const bt_field_path *sel_field_path = NULL;
737
738 if (fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR) {
739 sel_field_path =
740 bt_field_class_variant_with_selector_borrow_selector_field_path_const(
741 fc);
742 BT_ASSERT(sel_field_path);
743 }
744
745 g_string_append(ctx->str, " (");
746 write_uint_prop_value(ctx, option_count);
747 g_string_append_printf(ctx->str, " option%s, ",
748 plural(option_count));
749
750 if (sel_field_path) {
751 g_string_append(ctx->str, "Selector field path ");
752 write_field_path(ctx, sel_field_path);
753 }
754
755 g_string_append_c(ctx->str, ')');
756
757 if (option_count > 0) {
758 uint64_t i;
759
760 g_string_append_c(ctx->str, ':');
761 incr_indent(ctx);
762
763 for (i = 0; i < option_count; i++) {
764 write_variant_field_class_option(ctx, fc, i);
765 }
766
767 decr_indent(ctx);
768 }
769}
770
771static
772void write_field_class(struct details_write_ctx *ctx, const bt_field_class *fc)
773{
774 uint64_t i;
775 const char *type;
776 bt_field_class_type fc_type = bt_field_class_get_type(fc);
777
55478183
PP
778 /* Write field class's type */
779 switch (fc_type) {
dacaa55d
PP
780 case BT_FIELD_CLASS_TYPE_BOOL:
781 type = "Boolean";
782 break;
9684703d
PP
783 case BT_FIELD_CLASS_TYPE_BIT_ARRAY:
784 type = "Bit array";
785 break;
55478183
PP
786 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER:
787 type = "Unsigned integer";
788 break;
789 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER:
790 type = "Signed integer";
791 break;
792 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
793 type = "Unsigned enumeration";
794 break;
795 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
796 type = "Signed enumeration";
797 break;
798 case BT_FIELD_CLASS_TYPE_REAL:
799 type = "Real";
800 break;
801 case BT_FIELD_CLASS_TYPE_STRING:
802 type = "String";
803 break;
804 case BT_FIELD_CLASS_TYPE_STRUCTURE:
805 type = "Structure";
806 break;
807 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
808 type = "Static array";
809 break;
810 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
811 type = "Dynamic array";
812 break;
25510d56
PP
813 case BT_FIELD_CLASS_TYPE_OPTION:
814 type = "Option";
815 break;
45c51519
PP
816 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
817 type = "Variant (no selector)";
818 break;
819 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
820 type = "Variant (unsigned selector)";
821 break;
822 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
823 type = "Variant (signed selector)";
55478183
PP
824 break;
825 default:
826 abort();
827 }
828
829 g_string_append_printf(ctx->str, "%s%s%s",
830 color_fg_blue(ctx), type, color_reset(ctx));
831
832 /* Write field class's properties */
833 switch (fc_type) {
834 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER:
835 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER:
836 write_sp(ctx);
837 write_int_field_class_props(ctx, fc, true);
838 break;
839 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
840 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
841 {
842 uint64_t mapping_count =
843 bt_field_class_enumeration_get_mapping_count(fc);
844
845 write_sp(ctx);
846 write_int_field_class_props(ctx, fc, false);
847 g_string_append(ctx->str, ", ");
848 write_uint_prop_value(ctx, mapping_count);
849 g_string_append_printf(ctx->str, " mapping%s)",
850 plural(mapping_count));
851
852 if (mapping_count > 0) {
853 g_string_append_c(ctx->str, ':');
854 incr_indent(ctx);
855 write_enum_field_class_mappings(ctx, fc);
856 decr_indent(ctx);
857 }
858
859 break;
860 }
861 case BT_FIELD_CLASS_TYPE_REAL:
862 if (bt_field_class_real_is_single_precision(fc)) {
863 g_string_append(ctx->str, " (Single precision)");
864 } else {
865 g_string_append(ctx->str, " (Double precision)");
866 }
867
868 break;
869 case BT_FIELD_CLASS_TYPE_STRUCTURE:
870 {
871 uint64_t member_count =
872 bt_field_class_structure_get_member_count(fc);
873
874 g_string_append(ctx->str, " (");
875 write_uint_prop_value(ctx, member_count);
876 g_string_append_printf(ctx->str, " member%s)",
877 plural(member_count));
878
879 if (member_count > 0) {
880 g_string_append_c(ctx->str, ':');
881 incr_indent(ctx);
882
883 for (i = 0; i < member_count; i++) {
884 const bt_field_class_structure_member *member =
885 bt_field_class_structure_borrow_member_by_index_const(
886 fc, i);
887
888 write_nl(ctx);
45c51519 889 write_compound_member_name(ctx,
55478183 890 bt_field_class_structure_member_get_name(member));
45c51519
PP
891 write_sp(ctx);
892 write_field_class(ctx,
893 bt_field_class_structure_member_borrow_field_class_const(member));
55478183
PP
894 }
895
896 decr_indent(ctx);
897 }
898
899 break;
900 }
901 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
902 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
903 if (fc_type == BT_FIELD_CLASS_TYPE_STATIC_ARRAY) {
904 g_string_append(ctx->str, " (Length ");
905 write_uint_prop_value(ctx,
9c08c816 906 bt_field_class_array_static_get_length(fc));
55478183
PP
907 g_string_append_c(ctx->str, ')');
908 } else {
909 const bt_field_path *length_field_path =
9c08c816 910 bt_field_class_array_dynamic_borrow_length_field_path_const(
55478183
PP
911 fc);
912
913 if (length_field_path) {
914 g_string_append(ctx->str, " (Length field path ");
915 write_field_path(ctx, length_field_path);
916 g_string_append_c(ctx->str, ')');
917 }
918 }
919
920 g_string_append_c(ctx->str, ':');
921 write_nl(ctx);
922 incr_indent(ctx);
45c51519
PP
923 write_compound_member_name(ctx, "Element");
924 write_sp(ctx);
55478183 925 write_field_class(ctx,
45c51519 926 bt_field_class_array_borrow_element_field_class_const(fc));
55478183
PP
927 decr_indent(ctx);
928 break;
25510d56
PP
929 case BT_FIELD_CLASS_TYPE_OPTION:
930 {
931 const bt_field_path *selector_field_path =
932 bt_field_class_option_borrow_selector_field_path_const(fc);
933
934 if (selector_field_path) {
935 g_string_append(ctx->str, " (Selector field path ");
936 write_field_path(ctx, selector_field_path);
937 g_string_append_c(ctx->str, ')');
938 }
939
940 g_string_append_c(ctx->str, ':');
941 write_nl(ctx);
942 incr_indent(ctx);
943 write_compound_member_name(ctx, "Content");
944 write_sp(ctx);
945 write_field_class(ctx,
946 bt_field_class_option_borrow_field_class_const(fc));
947 decr_indent(ctx);
948 break;
949 }
45c51519
PP
950 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
951 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
952 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
953 write_variant_field_class(ctx, fc);
55478183 954 break;
55478183
PP
955 default:
956 break;
957 }
958}
959
960static
961void write_root_field_class(struct details_write_ctx *ctx, const char *name,
962 const bt_field_class *fc)
963{
964 BT_ASSERT(name);
965 BT_ASSERT(fc);
966 write_indent(ctx);
967 write_prop_name(ctx, name);
968 g_string_append(ctx->str, ": ");
45c51519 969 write_field_class(ctx, fc);
55478183
PP
970 write_nl(ctx);
971}
972
973static
974void write_event_class(struct details_write_ctx *ctx, const bt_event_class *ec)
975{
976 const char *name = bt_event_class_get_name(ec);
977 const char *emf_uri;
978 const bt_field_class *fc;
979 bt_event_class_log_level log_level;
980
981 write_indent(ctx);
982 write_obj_type_name(ctx, "Event class");
983
984 /* Write name and ID */
985 if (name) {
986 g_string_append_printf(ctx->str, " `%s%s%s`",
987 color_fg_green(ctx), name, color_reset(ctx));
988 }
989
990 g_string_append(ctx->str, " (ID ");
991 write_uint_prop_value(ctx, bt_event_class_get_id(ec));
992 g_string_append(ctx->str, "):\n");
993
994 /* Write properties */
995 incr_indent(ctx);
996
997 /* Write log level */
998 if (bt_event_class_get_log_level(ec, &log_level) ==
999 BT_PROPERTY_AVAILABILITY_AVAILABLE) {
1000 const char *ll_str = NULL;
1001
1002 switch (log_level) {
1003 case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
1004 ll_str = "Emergency";
1005 break;
1006 case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
1007 ll_str = "Alert";
1008 break;
1009 case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
1010 ll_str = "Critical";
1011 break;
1012 case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
1013 ll_str = "Error";
1014 break;
1015 case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
1016 ll_str = "Warning";
1017 break;
1018 case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
1019 ll_str = "Notice";
1020 break;
1021 case BT_EVENT_CLASS_LOG_LEVEL_INFO:
1022 ll_str = "Info";
1023 break;
1024 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
1025 ll_str = "Debug (system)";
1026 break;
1027 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
1028 ll_str = "Debug (program)";
1029 break;
1030 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
1031 ll_str = "Debug (process)";
1032 break;
1033 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
1034 ll_str = "Debug (module)";
1035 break;
1036 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
1037 ll_str = "Debug (unit)";
1038 break;
1039 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
1040 ll_str = "Debug (function)";
1041 break;
1042 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
1043 ll_str = "Debug (line)";
1044 break;
1045 case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
1046 ll_str = "Debug";
1047 break;
1048 default:
1049 abort();
1050 }
1051
1052 write_str_prop_line(ctx, "Log level", ll_str);
1053 }
1054
1055 /* Write EMF URI */
1056 emf_uri = bt_event_class_get_emf_uri(ec);
1057 if (emf_uri) {
1058 write_str_prop_line(ctx, "EMF URI", emf_uri);
1059 }
1060
1061 /* Write specific context field class */
1062 fc = bt_event_class_borrow_specific_context_field_class_const(ec);
1063 if (fc) {
1064 write_root_field_class(ctx, "Specific context field class", fc);
1065 }
1066
1067 /* Write payload field class */
1068 fc = bt_event_class_borrow_payload_field_class_const(ec);
1069 if (fc) {
1070 write_root_field_class(ctx, "Payload field class", fc);
1071 }
1072
1073 decr_indent(ctx);
1074}
1075
1076static
1077void write_clock_class_prop_lines(struct details_write_ctx *ctx,
1078 const bt_clock_class *cc)
1079{
1080 int64_t offset_seconds;
1081 uint64_t offset_cycles;
1082 const char *str;
1083
1084 str = bt_clock_class_get_name(cc);
1085 if (str) {
1086 write_str_prop_line(ctx, "Name", str);
1087 }
1088
1089 str = bt_clock_class_get_description(cc);
1090 if (str) {
1091 write_str_prop_line(ctx, "Description", str);
1092 }
1093
1094 write_uint_prop_line(ctx, "Frequency (Hz)",
1095 bt_clock_class_get_frequency(cc));
1096 write_uint_prop_line(ctx, "Precision (cycles)",
1097 bt_clock_class_get_precision(cc));
1098 bt_clock_class_get_offset(cc, &offset_seconds, &offset_cycles);
1099 write_int_prop_line(ctx, "Offset (s)", offset_seconds);
1100 write_uint_prop_line(ctx, "Offset (cycles)", offset_cycles);
1101 write_bool_prop_line(ctx, "Origin is Unix epoch",
1102 bt_clock_class_origin_is_unix_epoch(cc));
1103
1104 if (ctx->details_comp->cfg.with_uuid) {
1105 bt_uuid uuid = bt_clock_class_get_uuid(cc);
1106
1107 if (uuid) {
1108 write_uuid_prop_line(ctx, "UUID", uuid);
1109 }
1110 }
1111}
1112
1113static
1114gint compare_event_classes(const bt_event_class **a, const bt_event_class **b)
1115{
1116 uint64_t id_a = bt_event_class_get_id(*a);
1117 uint64_t id_b = bt_event_class_get_id(*b);
1118
1119 if (id_a < id_b) {
1120 return -1;
1121 } else if (id_a > id_b) {
1122 return 1;
1123 } else {
1124 return 0;
1125 }
1126}
1127
1128static
1129void write_stream_class(struct details_write_ctx *ctx,
1130 const bt_stream_class *sc)
1131{
1132 const bt_field_class *fc;
1133 GPtrArray *event_classes = g_ptr_array_new();
1134 uint64_t i;
1135
1136 write_indent(ctx);
1137 write_obj_type_name(ctx, "Stream class");
1138
1139 /* Write name and ID */
1140 if (ctx->details_comp->cfg.with_stream_class_name) {
1141 const char *name = bt_stream_class_get_name(sc);
1142
1143 if (name) {
1144 g_string_append(ctx->str, " `");
1145 write_str_prop_value(ctx, name);
1146 g_string_append(ctx->str, "`");
1147 }
1148 }
1149
1150 g_string_append(ctx->str, " (ID ");
1151 write_uint_prop_value(ctx, bt_stream_class_get_id(sc));
1152 g_string_append(ctx->str, "):\n");
1153
1154 /* Write properties */
1155 incr_indent(ctx);
1156
1157 /* Write configuration */
1158 write_bool_prop_line(ctx,
26fc5aed
PP
1159 "Supports packets", bt_stream_class_supports_packets(sc));
1160
1161 if (bt_stream_class_supports_packets(sc)) {
1162 write_bool_prop_line(ctx,
1163 "Packets have beginning default clock snapshot",
1164 bt_stream_class_packets_have_beginning_default_clock_snapshot(sc));
1165 write_bool_prop_line(ctx,
1166 "Packets have end default clock snapshot",
1167 bt_stream_class_packets_have_end_default_clock_snapshot(sc));
1168 }
1169
55478183
PP
1170 write_bool_prop_line(ctx,
1171 "Supports discarded events",
1172 bt_stream_class_supports_discarded_events(sc));
a3c75374
PP
1173
1174 if (bt_stream_class_supports_discarded_events(sc)) {
1175 write_bool_prop_line(ctx,
1176 "Discarded events have default clock snapshots",
1177 bt_stream_class_discarded_events_have_default_clock_snapshots(sc));
1178 }
1179
55478183
PP
1180 write_bool_prop_line(ctx,
1181 "Supports discarded packets",
1182 bt_stream_class_supports_discarded_packets(sc));
a3c75374
PP
1183
1184 if (bt_stream_class_supports_discarded_packets(sc)) {
1185 write_bool_prop_line(ctx,
1186 "Discarded packets have default clock snapshots",
1187 bt_stream_class_discarded_packets_have_default_clock_snapshots(sc));
1188 }
55478183
PP
1189
1190 /* Write default clock class */
1191 if (bt_stream_class_borrow_default_clock_class_const(sc)) {
1192 write_indent(ctx);
1193 write_prop_name(ctx, "Default clock class");
1194 g_string_append_c(ctx->str, ':');
1195 write_nl(ctx);
1196 incr_indent(ctx);
1197 write_clock_class_prop_lines(ctx,
1198 bt_stream_class_borrow_default_clock_class_const(sc));
1199 decr_indent(ctx);
1200 }
1201
1202 fc = bt_stream_class_borrow_packet_context_field_class_const(sc);
1203 if (fc) {
1204 write_root_field_class(ctx, "Packet context field class", fc);
1205 }
1206
1207 fc = bt_stream_class_borrow_event_common_context_field_class_const(sc);
1208 if (fc) {
1209 write_root_field_class(ctx, "Event common context field class",
1210 fc);
1211 }
1212
1213 for (i = 0; i < bt_stream_class_get_event_class_count(sc); i++) {
1214 g_ptr_array_add(event_classes,
1215 (gpointer) bt_stream_class_borrow_event_class_by_index_const(
1216 sc, i));
1217 }
1218
1219 g_ptr_array_sort(event_classes, (GCompareFunc) compare_event_classes);
1220
1221 for (i = 0; i < event_classes->len; i++) {
1222 write_event_class(ctx, event_classes->pdata[i]);
1223 }
1224
1225 decr_indent(ctx);
1226 g_ptr_array_free(event_classes, TRUE);
1227}
1228
1229static
1230gint compare_stream_classes(const bt_stream_class **a, const bt_stream_class **b)
1231{
1232 uint64_t id_a = bt_stream_class_get_id(*a);
1233 uint64_t id_b = bt_stream_class_get_id(*b);
1234
1235 if (id_a < id_b) {
1236 return -1;
1237 } else if (id_a > id_b) {
1238 return 1;
1239 } else {
1240 return 0;
1241 }
1242}
1243
1244static
1245gint compare_strings(const char **a, const char **b)
1246{
1247 return strcmp(*a, *b);
1248}
1249
1250static
1251void write_trace_class(struct details_write_ctx *ctx, const bt_trace_class *tc)
1252{
1253 GPtrArray *stream_classes = g_ptr_array_new();
55478183
PP
1254 uint64_t i;
1255 bool printed_prop = false;
1256
1257 write_indent(ctx);
1258 write_obj_type_name(ctx, "Trace class");
1259
55478183
PP
1260 for (i = 0; i < bt_trace_class_get_stream_class_count(tc); i++) {
1261 g_ptr_array_add(stream_classes,
1262 (gpointer) bt_trace_class_borrow_stream_class_by_index_const(
1263 tc, i));
1264 }
1265
1266 g_ptr_array_sort(stream_classes, (GCompareFunc) compare_stream_classes);
1267
1268 if (stream_classes->len > 0) {
1269 if (!printed_prop) {
1270 g_string_append(ctx->str, ":\n");
1271 printed_prop = true;
1272 }
1273 }
1274
335a2da5
PP
1275 incr_indent(ctx);
1276
55478183
PP
1277 for (i = 0; i < stream_classes->len; i++) {
1278 write_stream_class(ctx, stream_classes->pdata[i]);
1279 }
1280
55478183
PP
1281 if (!printed_prop) {
1282 write_nl(ctx);
1283 }
1284
335a2da5 1285 decr_indent(ctx);
55478183 1286 g_ptr_array_free(stream_classes, TRUE);
55478183
PP
1287}
1288
1289static
1290int try_write_meta(struct details_write_ctx *ctx, const bt_trace_class *tc,
1291 const bt_stream_class *sc, const bt_event_class *ec)
1292{
1293 int ret = 0;
1294
1295 BT_ASSERT(tc);
1296
1297 if (details_need_to_write_trace_class(ctx, tc)) {
1298 uint64_t sc_i;
1299
1300 if (ctx->details_comp->cfg.compact &&
1301 ctx->details_comp->printed_something) {
1302 /*
1303 * There are no empty line between messages in
1304 * compact mode, so write one here to decouple
1305 * the trace class from the next message.
1306 */
1307 write_nl(ctx);
1308 }
1309
1310 /*
1311 * write_trace_class() also writes all its stream
1312 * classes their event classes, so we don't need to
1313 * rewrite `sc`.
1314 */
1315 write_trace_class(ctx, tc);
1316 write_nl(ctx);
1317
1318 /*
1319 * Mark this trace class as written, as well as all
1320 * its stream classes and their event classes.
1321 */
1322 ret = details_did_write_trace_class(ctx, tc);
1323 if (ret) {
1324 goto end;
1325 }
1326
1327 for (sc_i = 0; sc_i < bt_trace_class_get_stream_class_count(tc);
1328 sc_i++) {
1329 uint64_t ec_i;
1330 const bt_stream_class *tc_sc =
1331 bt_trace_class_borrow_stream_class_by_index_const(
1332 tc, sc_i);
1333
1334 details_did_write_meta_object(ctx, tc, tc_sc);
1335
1336 for (ec_i = 0; ec_i <
1337 bt_stream_class_get_event_class_count(tc_sc);
1338 ec_i++) {
1339 details_did_write_meta_object(ctx, tc,
1340 bt_stream_class_borrow_event_class_by_index_const(
1341 tc_sc, ec_i));
1342 }
1343 }
1344
1345 goto end;
1346 }
1347
1348 if (sc && details_need_to_write_meta_object(ctx, tc, sc)) {
1349 uint64_t ec_i;
1350
1351 BT_ASSERT(tc);
1352
1353 if (ctx->details_comp->cfg.compact &&
1354 ctx->details_comp->printed_something) {
1355 /*
1356 * There are no empty line between messages in
1357 * compact mode, so write one here to decouple
1358 * the stream class from the next message.
1359 */
1360 write_nl(ctx);
1361 }
1362
1363 /*
1364 * write_stream_class() also writes all its event
1365 * classes, so we don't need to rewrite `ec`.
1366 */
1367 write_stream_class(ctx, sc);
1368 write_nl(ctx);
1369
1370 /*
1371 * Mark this stream class as written, as well as all its
1372 * event classes.
1373 */
1374 details_did_write_meta_object(ctx, tc, sc);
1375
1376 for (ec_i = 0; ec_i <
1377 bt_stream_class_get_event_class_count(sc);
1378 ec_i++) {
1379 details_did_write_meta_object(ctx, tc,
1380 bt_stream_class_borrow_event_class_by_index_const(
1381 sc, ec_i));
1382 }
1383
1384 goto end;
1385 }
1386
1387 if (ec && details_need_to_write_meta_object(ctx, tc, ec)) {
1388 BT_ASSERT(sc);
1389
1390 if (ctx->details_comp->cfg.compact &&
1391 ctx->details_comp->printed_something) {
1392 /*
1393 * There are no empty line between messages in
1394 * compact mode, so write one here to decouple
1395 * the event class from the next message.
1396 */
1397 write_nl(ctx);
1398 }
1399
1400 write_event_class(ctx, ec);
1401 write_nl(ctx);
1402 details_did_write_meta_object(ctx, tc, ec);
1403 goto end;
1404 }
1405
1406end:
1407 return ret;
1408}
1409
1410static
1411void write_time_str(struct details_write_ctx *ctx, const char *str)
1412{
1413 if (!ctx->details_comp->cfg.with_time) {
1414 goto end;
1415 }
1416
1417 g_string_append_printf(ctx->str, "[%s%s%s%s]",
1418 color_bold(ctx), color_fg_blue(ctx), str, color_reset(ctx));
1419
1420 if (ctx->details_comp->cfg.compact) {
1421 write_sp(ctx);
1422 } else {
1423 write_nl(ctx);
1424 }
1425
1426end:
1427 return;
1428}
1429
1430static
1431void write_time(struct details_write_ctx *ctx, const bt_clock_snapshot *cs)
1432{
d24d5663 1433 bt_clock_snapshot_get_ns_from_origin_status cs_status;
55478183
PP
1434 int64_t ns_from_origin;
1435 char buf[32];
1436
1437 if (!ctx->details_comp->cfg.with_time) {
1438 goto end;
1439 }
1440
1441 format_uint(buf, bt_clock_snapshot_get_value(cs), 10);
1442 g_string_append_printf(ctx->str, "[%s%s%s%s%s",
1443 color_bold(ctx), color_fg_blue(ctx), buf,
1444 color_reset(ctx),
1445 ctx->details_comp->cfg.compact ? "" : " cycles");
d24d5663
PP
1446 cs_status = bt_clock_snapshot_get_ns_from_origin(cs, &ns_from_origin);
1447 if (cs_status == BT_CLOCK_SNAPSHOT_GET_NS_FROM_ORIGIN_STATUS_OK) {
55478183
PP
1448 format_int(buf, ns_from_origin, 10);
1449 g_string_append_printf(ctx->str, "%s %s%s%s%s%s",
1450 ctx->details_comp->cfg.compact ? "" : ",",
1451 color_bold(ctx), color_fg_blue(ctx), buf,
1452 color_reset(ctx),
1453 ctx->details_comp->cfg.compact ? "" : " ns from origin");
1454 }
1455
1456 g_string_append(ctx->str, "]");
1457
1458 if (ctx->details_comp->cfg.compact) {
1459 write_sp(ctx);
1460 } else {
1461 write_nl(ctx);
1462 }
1463
1464end:
1465 return;
1466}
1467
1468static
1469int write_message_follow_tag(struct details_write_ctx *ctx,
1470 const bt_stream *stream)
1471{
1472 int ret;
1473 uint64_t unique_trace_id;
1474 const bt_stream_class *sc = bt_stream_borrow_class_const(stream);
1475 const bt_trace *trace = bt_stream_borrow_trace_const(stream);
1476
1477 ret = details_trace_unique_id(ctx, trace, &unique_trace_id);
1478 if (ret) {
1479 goto end;
1480 }
1481
1482 if (ctx->details_comp->cfg.compact) {
1483 g_string_append_printf(ctx->str,
1484 "%s{%s%" PRIu64 " %" PRIu64 " %" PRIu64 "%s%s}%s ",
1485 color_fg_cyan(ctx), color_bold(ctx),
1486 unique_trace_id, bt_stream_class_get_id(sc),
1487 bt_stream_get_id(stream),
1488 color_reset(ctx), color_fg_cyan(ctx), color_reset(ctx));
1489 } else {
1490 g_string_append_printf(ctx->str,
1491 "%s{Trace %s%" PRIu64 "%s%s, Stream class ID %s%" PRIu64 "%s%s, Stream ID %s%" PRIu64 "%s%s}%s\n",
1492 color_fg_cyan(ctx),
1493 color_bold(ctx), unique_trace_id,
1494 color_reset(ctx), color_fg_cyan(ctx),
1495 color_bold(ctx), bt_stream_class_get_id(sc),
1496 color_reset(ctx), color_fg_cyan(ctx),
1497 color_bold(ctx), bt_stream_get_id(stream),
1498 color_reset(ctx), color_fg_cyan(ctx),
1499 color_reset(ctx));
1500 }
1501
1502end:
1503 return ret;
1504}
1505
1506static
1507void write_field(struct details_write_ctx *ctx, const bt_field *field,
1508 const char *name)
1509{
1510 uint64_t i;
1511 bt_field_class_type fc_type = bt_field_get_class_type(field);
1512 const bt_field_class *fc;
1513 char buf[64];
1514
1515 /* Write field's name */
1516 if (name) {
1517 write_compound_member_name(ctx, name);
1518 }
1519
1520 /* Write field's value */
1521 switch (fc_type) {
dacaa55d
PP
1522 case BT_FIELD_CLASS_TYPE_BOOL:
1523 write_sp(ctx);
1524 write_bool_prop_value(ctx, bt_field_bool_get_value(field));
1525 break;
9684703d
PP
1526 case BT_FIELD_CLASS_TYPE_BIT_ARRAY:
1527 format_uint(buf, bt_field_bit_array_get_value_as_integer(field),
1528 16);
1529 write_sp(ctx);
1530 write_uint_str_prop_value(ctx, buf);
1531 break;
55478183
PP
1532 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER:
1533 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
1534 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER:
1535 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
1536 {
1537 unsigned int fmt_base;
1538 bt_field_class_integer_preferred_display_base base;
1539
1540 fc = bt_field_borrow_class_const(field);
1541 base = bt_field_class_integer_get_preferred_display_base(fc);
1542
1543 switch (base) {
1544 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL:
1545 fmt_base = 10;
1546 break;
1547 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL:
1548 fmt_base = 8;
1549 break;
1550 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY:
1551 fmt_base = 2;
1552 break;
1553 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL:
1554 fmt_base = 16;
1555 break;
1556 default:
1557 abort();
1558 }
1559
1560 if (fc_type == BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER ||
1561 fc_type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION) {
1562 format_uint(buf,
9c08c816 1563 bt_field_integer_unsigned_get_value(field),
55478183
PP
1564 fmt_base);
1565 write_sp(ctx);
1566 write_uint_str_prop_value(ctx, buf);
1567 } else {
1568 format_int(buf,
9c08c816 1569 bt_field_integer_signed_get_value(field),
55478183
PP
1570 fmt_base);
1571 write_sp(ctx);
1572 write_int_str_prop_value(ctx, buf);
1573 }
1574
1575 break;
1576 }
1577 case BT_FIELD_CLASS_TYPE_REAL:
1578 write_sp(ctx);
1579 write_float_prop_value(ctx, bt_field_real_get_value(field));
1580 break;
1581 case BT_FIELD_CLASS_TYPE_STRING:
1582 write_sp(ctx);
1583 write_str_prop_value(ctx, bt_field_string_get_value(field));
1584 break;
1585 case BT_FIELD_CLASS_TYPE_STRUCTURE:
1586 {
1587 uint64_t member_count;
1588
1589 fc = bt_field_borrow_class_const(field);
1590 member_count = bt_field_class_structure_get_member_count(fc);
1591
1592 if (member_count > 0) {
1593 incr_indent(ctx);
1594
1595 for (i = 0; i < member_count; i++) {
1596 const bt_field_class_structure_member *member =
1597 bt_field_class_structure_borrow_member_by_index_const(
1598 fc, i);
1599 const bt_field *member_field =
1600 bt_field_structure_borrow_member_field_by_index_const(
1601 field, i);
1602
1603 write_nl(ctx);
1604 write_field(ctx, member_field,
1605 bt_field_class_structure_member_get_name(member));
1606 }
1607
1608 decr_indent(ctx);
1609 } else {
8f512475
PP
1610 write_sp(ctx);
1611 write_none_prop_value(ctx, "Empty");
55478183
PP
1612 }
1613
1614 break;
1615 }
1616 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
1617 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
1618 {
1619 uint64_t length = bt_field_array_get_length(field);
1620
1621 if (length == 0) {
8f512475
PP
1622 write_sp(ctx);
1623 write_none_prop_value(ctx, "Empty");
55478183
PP
1624 } else {
1625 g_string_append(ctx->str, " Length ");
1626 write_uint_prop_value(ctx, length);
1627 g_string_append_c(ctx->str, ':');
1628 }
1629
1630 incr_indent(ctx);
1631
1632 for (i = 0; i < length; i++) {
1633 const bt_field *elem_field =
1634 bt_field_array_borrow_element_field_by_index_const(
1635 field, i);
1636
1637 write_nl(ctx);
1638 write_array_index(ctx, i);
1639 write_field(ctx, elem_field, NULL);
1640 }
1641
1642 decr_indent(ctx);
1643 break;
1644 }
25510d56
PP
1645 case BT_FIELD_CLASS_TYPE_OPTION:
1646 {
1647 const bt_field *content_field =
1648 bt_field_option_borrow_field_const(field);
1649
1650 if (!content_field) {
1651 write_sp(ctx);
1652 write_none_prop_value(ctx, "None");
1653 } else {
1654 write_field(ctx, content_field, NULL);
1655 }
1656
1657 break;
1658 }
45c51519
PP
1659 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
1660 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
1661 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
55478183
PP
1662 write_field(ctx,
1663 bt_field_variant_borrow_selected_option_field_const(
1664 field), NULL);
1665 break;
1666 default:
1667 abort();
1668 }
1669}
1670
1671static
1672void write_root_field(struct details_write_ctx *ctx, const char *name,
1673 const bt_field *field)
1674{
1675 BT_ASSERT(name);
1676 BT_ASSERT(field);
1677 write_indent(ctx);
1678 write_prop_name(ctx, name);
1679 g_string_append(ctx->str, ":");
1680 write_field(ctx, field, NULL);
1681 write_nl(ctx);
1682}
1683
1684static
1685int write_event_message(struct details_write_ctx *ctx,
1686 const bt_message *msg)
1687{
1688 int ret = 0;
1689 const bt_event *event = bt_message_event_borrow_event_const(msg);
1690 const bt_stream *stream = bt_event_borrow_stream_const(event);
1691 const bt_event_class *ec = bt_event_borrow_class_const(event);
1692 const bt_stream_class *sc = bt_event_class_borrow_stream_class_const(ec);
1693 const bt_trace_class *tc = bt_stream_class_borrow_trace_class_const(sc);
1694 const char *ec_name;
1695 const bt_field *field;
1696
1697 ret = try_write_meta(ctx, tc, sc, ec);
1698 if (ret) {
1699 goto end;
1700 }
1701
1702 /* Write time */
1703 if (bt_stream_class_borrow_default_clock_class_const(sc)) {
1704 write_time(ctx,
1705 bt_message_event_borrow_default_clock_snapshot_const(
1706 msg));
1707 }
1708
1709 /* Write follow tag for message */
1710 ret = write_message_follow_tag(ctx, stream);
1711 if (ret) {
1712 goto end;
1713 }
1714
1715 /* Write object's basic properties */
1716 write_obj_type_name(ctx, "Event");
1717 ec_name = bt_event_class_get_name(ec);
1718 if (ec_name) {
1719 g_string_append_printf(ctx->str, " `%s%s%s`",
1720 color_fg_green(ctx), ec_name, color_reset(ctx));
1721 }
1722
1723 g_string_append(ctx->str, " (");
1724
1725 if (!ctx->details_comp->cfg.compact) {
1726 g_string_append(ctx->str, "Class ID ");
1727 }
1728
1729 write_uint_prop_value(ctx, bt_event_class_get_id(ec));
1730 g_string_append(ctx->str, ")");
1731
1732 if (ctx->details_comp->cfg.compact) {
1733 write_nl(ctx);
1734 goto end;
1735 }
1736
1737 /* Write fields */
1738 g_string_append(ctx->str, ":\n");
1739 incr_indent(ctx);
1740 field = bt_event_borrow_common_context_field_const(event);
1741 if (field) {
1742 write_root_field(ctx, "Common context", field);
1743 }
1744
1745 field = bt_event_borrow_specific_context_field_const(event);
1746 if (field) {
1747 write_root_field(ctx, "Specific context", field);
1748 }
1749
1750 field = bt_event_borrow_payload_field_const(event);
1751 if (field) {
1752 write_root_field(ctx, "Payload", field);
1753 }
1754
1755 decr_indent(ctx);
1756
1757end:
1758
1759 return ret;
1760}
1761
1762static
1763gint compare_streams(const bt_stream **a, const bt_stream **b)
1764{
1765 uint64_t id_a = bt_stream_get_id(*a);
1766 uint64_t id_b = bt_stream_get_id(*b);
1767
1768 if (id_a < id_b) {
1769 return -1;
1770 } else if (id_a > id_b) {
1771 return 1;
1772 } else {
1773 const bt_stream_class *a_sc = bt_stream_borrow_class_const(*a);
1774 const bt_stream_class *b_sc = bt_stream_borrow_class_const(*b);
1775 uint64_t a_sc_id = bt_stream_class_get_id(a_sc);
1776 uint64_t b_sc_id = bt_stream_class_get_id(b_sc);
1777
1778 if (a_sc_id < b_sc_id) {
1779 return -1;
1780 } else if (a_sc_id > b_sc_id) {
1781 return 1;
1782 } else {
1783 return 0;
1784 }
1785 }
1786}
1787
1788static
1789void write_trace(struct details_write_ctx *ctx, const bt_trace *trace)
1790{
1791 const char *name;
55478183
PP
1792 GPtrArray *streams = g_ptr_array_new();
1793 uint64_t i;
1794 bool printed_prop = false;
335a2da5
PP
1795 GPtrArray *env_names = g_ptr_array_new();
1796 uint64_t env_count;
55478183
PP
1797
1798 write_indent(ctx);
1799 write_obj_type_name(ctx, "Trace");
1800
1801 /* Write name */
1802 if (ctx->details_comp->cfg.with_trace_name) {
1803 name = bt_trace_get_name(trace);
1804 if (name) {
1805 g_string_append(ctx->str, " `");
1806 write_str_prop_value(ctx, name);
1807 g_string_append(ctx->str, "`");
1808 }
1809 }
1810
1811 /* Write properties */
1812 incr_indent(ctx);
1813
335a2da5
PP
1814 /* Write UUID */
1815 if (ctx->details_comp->cfg.with_uuid) {
1816 bt_uuid uuid = bt_trace_get_uuid(trace);
1817
1818 if (uuid) {
55478183
PP
1819 if (!printed_prop) {
1820 g_string_append(ctx->str, ":\n");
1821 printed_prop = true;
1822 }
1823
335a2da5 1824 write_uuid_prop_line(ctx, "UUID", uuid);
55478183
PP
1825 }
1826 }
1827
335a2da5
PP
1828 /* Write environment */
1829 env_count = bt_trace_get_environment_entry_count(trace);
1830 if (env_count > 0) {
1831 if (!printed_prop) {
1832 g_string_append(ctx->str, ":\n");
1833 printed_prop = true;
1834 }
55478183 1835
335a2da5
PP
1836 write_indent(ctx);
1837 write_prop_name(ctx, "Environment");
1838 g_string_append(ctx->str, " (");
1839 write_uint_prop_value(ctx, env_count);
1840 g_string_append_printf(ctx->str, " entr%s):",
1841 env_count == 1 ? "y" : "ies");
1842 write_nl(ctx);
1843 incr_indent(ctx);
1844
1845 for (i = 0; i < env_count; i++) {
1846 const char *name;
1847 const bt_value *value;
1848
1849 bt_trace_borrow_environment_entry_by_index_const(
1850 trace, i, &name, &value);
1851 g_ptr_array_add(env_names, (gpointer) name);
1852 }
1853
1854 g_ptr_array_sort(env_names, (GCompareFunc) compare_strings);
1855
1856 for (i = 0; i < env_names->len; i++) {
1857 const char *name = env_names->pdata[i];
1858 const bt_value *value =
1859 bt_trace_borrow_environment_entry_value_by_name_const(
1860 trace, name);
1861
1862 BT_ASSERT(value);
1863 write_compound_member_name(ctx, name);
1864 write_sp(ctx);
1865
1866 if (bt_value_get_type(value) ==
1867 BT_VALUE_TYPE_SIGNED_INTEGER) {
1868 write_int_prop_value(ctx,
9c08c816 1869 bt_value_integer_signed_get(value));
335a2da5
PP
1870 } else if (bt_value_get_type(value) ==
1871 BT_VALUE_TYPE_STRING) {
1872 write_str_prop_value(ctx,
1873 bt_value_string_get(value));
1874 } else {
1875 abort();
55478183
PP
1876 }
1877
335a2da5 1878 write_nl(ctx);
55478183 1879 }
335a2da5
PP
1880
1881 decr_indent(ctx);
55478183
PP
1882 }
1883
1884 for (i = 0; i < bt_trace_get_stream_count(trace); i++) {
1885 g_ptr_array_add(streams,
1886 (gpointer) bt_trace_borrow_stream_by_index_const(
1887 trace, i));
1888 }
1889
1890 g_ptr_array_sort(streams, (GCompareFunc) compare_streams);
1891
1892 if (streams->len > 0 && !printed_prop) {
1893 g_string_append(ctx->str, ":\n");
1894 printed_prop = true;
1895 }
1896
1897 for (i = 0; i < streams->len; i++) {
1898 const bt_stream *stream = streams->pdata[i];
1899
1900 write_indent(ctx);
1901 write_obj_type_name(ctx, "Stream");
1902 g_string_append(ctx->str, " (ID ");
1903 write_uint_prop_value(ctx, bt_stream_get_id(stream));
1904 g_string_append(ctx->str, ", Class ID ");
1905 write_uint_prop_value(ctx, bt_stream_class_get_id(
1906 bt_stream_borrow_class_const(stream)));
1907 g_string_append(ctx->str, ")");
1908 write_nl(ctx);
1909 }
1910
1911 decr_indent(ctx);
1912
1913 if (!printed_prop) {
1914 write_nl(ctx);
1915 }
1916
1917 g_ptr_array_free(streams, TRUE);
335a2da5 1918 g_ptr_array_free(env_names, TRUE);
55478183
PP
1919}
1920
1921static
1922int write_stream_beginning_message(struct details_write_ctx *ctx,
1923 const bt_message *msg)
1924{
1925 int ret = 0;
1926 const bt_stream *stream =
1927 bt_message_stream_beginning_borrow_stream_const(msg);
1928 const bt_trace *trace = bt_stream_borrow_trace_const(stream);
1929 const bt_stream_class *sc = bt_stream_borrow_class_const(stream);
188edac1 1930 const bt_clock_class *cc = bt_stream_class_borrow_default_clock_class_const(sc);
55478183
PP
1931 const bt_trace_class *tc = bt_stream_class_borrow_trace_class_const(sc);
1932 const char *name;
1933
1934 ret = try_write_meta(ctx, tc, sc, NULL);
1935 if (ret) {
1936 goto end;
1937 }
1938
188edac1
SM
1939 /* Write time */
1940 if (cc) {
1941 const bt_clock_snapshot *cs;
1942 bt_message_stream_clock_snapshot_state cs_state =
1943 bt_message_stream_beginning_borrow_default_clock_snapshot_const(msg, &cs);
1944
1945 if (cs_state == BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN) {
1946 write_time(ctx, cs);
1947 } else {
1948 write_time_str(ctx, "Unknown");
1949 }
1950 }
1951
55478183
PP
1952 /* Write follow tag for message */
1953 ret = write_message_follow_tag(ctx, stream);
1954 if (ret) {
1955 goto end;
1956 }
1957
1958 /* Write stream properties */
1959 write_obj_type_name(ctx, "Stream beginning");
1960
1961 if (ctx->details_comp->cfg.compact) {
1962 write_nl(ctx);
1963 goto end;
1964 }
1965
1966 g_string_append(ctx->str, ":\n");
1967 incr_indent(ctx);
1968
1969 if (ctx->details_comp->cfg.with_stream_name) {
1970 name = bt_stream_get_name(stream);
1971 if (name) {
1972 write_str_prop_line(ctx, "Name", name);
1973 }
1974 }
1975
1976 if (ctx->details_comp->cfg.with_stream_class_name) {
1977 name = bt_stream_class_get_name(sc);
1978 if (name) {
1979 write_str_prop_line(ctx, "Class name", name);
1980 }
1981 }
1982
1983 write_trace(ctx, trace);
1984 decr_indent(ctx);
1985
1986end:
1987 return ret;
1988}
1989
1990static
1991int write_stream_end_message(struct details_write_ctx *ctx,
1992 const bt_message *msg)
1993{
1994 int ret = 0;
1995 const bt_stream *stream =
1996 bt_message_stream_end_borrow_stream_const(msg);
188edac1
SM
1997 const bt_stream_class *sc =
1998 bt_stream_borrow_class_const(stream);
1999 const bt_clock_class *cc =
2000 bt_stream_class_borrow_default_clock_class_const(sc);
55478183
PP
2001
2002 /* Write time */
188edac1
SM
2003 if (cc) {
2004 const bt_clock_snapshot *cs;
2005 bt_message_stream_clock_snapshot_state cs_state =
2006 bt_message_stream_end_borrow_default_clock_snapshot_const(msg, &cs);
55478183 2007
188edac1
SM
2008 if (cs_state == BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN) {
2009 write_time(ctx, cs);
2010 } else {
2011 write_time_str(ctx, "Unknown");
2012 }
55478183
PP
2013 }
2014
2015 /* Write follow tag for message */
2016 ret = write_message_follow_tag(ctx, stream);
2017 if (ret) {
2018 goto end;
2019 }
2020
188edac1
SM
2021 /* Write stream properties */
2022 write_obj_type_name(ctx, "Stream end\n");
55478183
PP
2023
2024end:
2025 return ret;
2026}
2027
2028static
2029int write_packet_beginning_message(struct details_write_ctx *ctx,
2030 const bt_message *msg)
2031{
2032 int ret = 0;
2033 const bt_packet *packet =
2034 bt_message_packet_beginning_borrow_packet_const(msg);
2035 const bt_stream *stream = bt_packet_borrow_stream_const(packet);
2036 const bt_stream_class *sc = bt_stream_borrow_class_const(stream);
2037 const bt_field *field;
2038
2039 /* Write time */
2040 if (bt_stream_class_packets_have_beginning_default_clock_snapshot(sc)) {
2041 write_time(ctx,
2042 bt_message_packet_beginning_borrow_default_clock_snapshot_const(
2043 msg));
2044 }
2045
2046 /* Write follow tag for message */
2047 ret = write_message_follow_tag(ctx, stream);
2048 if (ret) {
2049 goto end;
2050 }
2051
2052 write_obj_type_name(ctx, "Packet beginning");
2053
2054 if (ctx->details_comp->cfg.compact) {
2055 write_nl(ctx);
2056 goto end;
2057 }
2058
2059 /* Write field */
2060 g_string_append(ctx->str, ":\n");
2061 incr_indent(ctx);
2062 field = bt_packet_borrow_context_field_const(packet);
2063 if (field) {
2064 write_root_field(ctx, "Context", field);
2065 }
2066
2067 decr_indent(ctx);
2068
2069end:
2070 return ret;
2071}
2072
2073static
2074int write_discarded_items_message(struct details_write_ctx *ctx,
2075 const char *name, const bt_stream *stream,
2076 const bt_clock_snapshot *beginning_cs,
2077 const bt_clock_snapshot *end_cs, uint64_t count)
2078{
2079 int ret = 0;
2080
2081 /* Write times */
2082 if (beginning_cs) {
2083 write_time(ctx, beginning_cs);
2084 BT_ASSERT(end_cs);
2085 write_time(ctx, end_cs);
2086 }
2087
2088 /* Write follow tag for message */
2089 ret = write_message_follow_tag(ctx, stream);
2090 if (ret) {
2091 goto end;
2092 }
2093
2094 write_obj_type_name(ctx, "Discarded ");
2095 write_obj_type_name(ctx, name);
2096
2097 /* Write count */
2098 if (count == UINT64_C(-1)) {
2099 write_nl(ctx);
2100 goto end;
2101 }
2102
2103 g_string_append(ctx->str, " (");
2104 write_uint_prop_value(ctx, count);
2105 g_string_append_printf(ctx->str, " %s)\n", name);
2106
2107end:
2108 return ret;
2109}
2110
2111static
2112int write_discarded_events_message(struct details_write_ctx *ctx,
2113 const bt_message *msg)
2114{
2115 const bt_stream *stream = bt_message_discarded_events_borrow_stream_const(
2116 msg);
2117 const bt_stream_class *sc = bt_stream_borrow_class_const(stream);
2118 const bt_clock_snapshot *beginning_cs = NULL;
2119 const bt_clock_snapshot *end_cs = NULL;
2120 uint64_t count;
2121
2122 if (bt_stream_class_discarded_events_have_default_clock_snapshots(sc)) {
2123 beginning_cs =
2124 bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
2125 msg);
2126 end_cs =
2127 bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
2128 msg);
2129 }
2130
2131 if (bt_message_discarded_events_get_count(msg, &count) !=
2132 BT_PROPERTY_AVAILABILITY_AVAILABLE) {
2133 count = UINT64_C(-1);
2134 }
2135
2136 return write_discarded_items_message(ctx, "events", stream,
2137 beginning_cs, end_cs, count);
2138}
2139
2140static
2141int write_discarded_packets_message(struct details_write_ctx *ctx,
2142 const bt_message *msg)
2143{
2144 const bt_stream *stream = bt_message_discarded_packets_borrow_stream_const(
2145 msg);
2146 const bt_stream_class *sc = bt_stream_borrow_class_const(stream);
2147 const bt_clock_snapshot *beginning_cs = NULL;
2148 const bt_clock_snapshot *end_cs = NULL;
2149 uint64_t count;
2150
2151 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(sc)) {
2152 beginning_cs =
2153 bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
2154 msg);
2155 end_cs =
2156 bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
2157 msg);
2158 }
2159
2160 if (bt_message_discarded_packets_get_count(msg, &count) !=
2161 BT_PROPERTY_AVAILABILITY_AVAILABLE) {
2162 count = UINT64_C(-1);
2163 }
2164
2165 return write_discarded_items_message(ctx, "packets", stream,
2166 beginning_cs, end_cs, count);
2167}
2168
2169static
2170int write_packet_end_message(struct details_write_ctx *ctx,
2171 const bt_message *msg)
2172{
2173 int ret = 0;
2174 const bt_packet *packet =
2175 bt_message_packet_end_borrow_packet_const(msg);
2176 const bt_stream *stream = bt_packet_borrow_stream_const(packet);
2177 const bt_stream_class *sc = bt_stream_borrow_class_const(stream);
2178
2179 /* Write time */
2180 if (bt_stream_class_packets_have_end_default_clock_snapshot(sc)) {
2181 write_time(ctx,
2182 bt_message_packet_end_borrow_default_clock_snapshot_const(
2183 msg));
2184 }
2185
2186 /* Write follow tag for message */
2187 ret = write_message_follow_tag(ctx, stream);
2188 if (ret) {
2189 goto end;
2190 }
2191
2192 write_obj_type_name(ctx, "Packet end");
2193 write_nl(ctx);
2194
2195end:
2196 return ret;
2197}
2198
2199static
2200int write_message_iterator_inactivity_message(struct details_write_ctx *ctx,
2201 const bt_message *msg)
2202{
2203 int ret = 0;
2204 const bt_clock_snapshot *cs =
2205 bt_message_message_iterator_inactivity_borrow_default_clock_snapshot_const(
2206 msg);
2207
2208 /* Write time */
2209 write_time(ctx, cs);
2210 write_obj_type_name(ctx, "Message iterator inactivity");
2211
2212 if (ctx->details_comp->cfg.compact) {
2213 write_nl(ctx);
2214 goto end;
2215 }
2216
2217 /* Write clock class properties */
2218 g_string_append(ctx->str, ":\n");
2219 incr_indent(ctx);
2220 write_indent(ctx);
2221 write_prop_name(ctx, "Clock class");
2222 g_string_append_c(ctx->str, ':');
2223 write_nl(ctx);
2224 incr_indent(ctx);
2225 write_clock_class_prop_lines(ctx,
2226 bt_clock_snapshot_borrow_clock_class_const(cs));
2227 decr_indent(ctx);
2228
2229end:
2230 return ret;
2231}
2232
2233BT_HIDDEN
2234int details_write_message(struct details_comp *details_comp,
2235 const bt_message *msg)
2236{
2237 int ret = 0;
2238 struct details_write_ctx ctx = {
2239 .details_comp = details_comp,
2240 .str = details_comp->str,
2241 .indent_level = 0,
2242 };
2243
2244 /* Reset output buffer */
2245 g_string_assign(details_comp->str, "");
2246
2247 if (details_comp->printed_something && !details_comp->cfg.compact) {
2248 write_nl(&ctx);
2249 }
2250
2251 switch (bt_message_get_type(msg)) {
2252 case BT_MESSAGE_TYPE_EVENT:
2253 ret = write_event_message(&ctx, msg);
2254 break;
2255 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY:
2256 ret = write_message_iterator_inactivity_message(&ctx, msg);
2257 break;
2258 case BT_MESSAGE_TYPE_STREAM_BEGINNING:
2259 ret = write_stream_beginning_message(&ctx, msg);
2260 break;
2261 case BT_MESSAGE_TYPE_STREAM_END:
2262 ret = write_stream_end_message(&ctx, msg);
2263 break;
2264 case BT_MESSAGE_TYPE_PACKET_BEGINNING:
2265 ret = write_packet_beginning_message(&ctx, msg);
2266 break;
2267 case BT_MESSAGE_TYPE_PACKET_END:
2268 ret = write_packet_end_message(&ctx, msg);
2269 break;
55478183
PP
2270 case BT_MESSAGE_TYPE_DISCARDED_EVENTS:
2271 ret = write_discarded_events_message(&ctx, msg);
2272 break;
2273 case BT_MESSAGE_TYPE_DISCARDED_PACKETS:
2274 ret = write_discarded_packets_message(&ctx, msg);
2275 break;
2276 default:
2277 abort();
2278 }
2279
2280 return ret;
2281}
This page took 0.118386 seconds and 4 git commands to generate.