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