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