text output: wire up clock options, error checking
[babeltrace.git] / plugins / text / print.c
1 /*
2 * print.c
3 *
4 * Babeltrace CTF Text Output Plugin Event Printing
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30 #include <babeltrace/ctf-ir/event.h>
31 #include <babeltrace/ctf-ir/event-class.h>
32 #include <babeltrace/ctf-ir/packet.h>
33 #include <babeltrace/ctf-ir/stream.h>
34 #include <babeltrace/ctf-ir/stream-class.h>
35 #include <babeltrace/ctf-ir/clock.h>
36 #include <babeltrace/ctf-ir/field-types.h>
37 #include <babeltrace/ctf-ir/fields.h>
38 #include <babeltrace/ctf-ir/trace.h>
39 #include <babeltrace/bitfield.h>
40 #include <inttypes.h>
41 #include "text.h"
42
43 #define NSEC_PER_SEC 1000000000LL
44
45 static inline
46 const char *rem_(const char *str)
47 {
48 if (str[0] == '_')
49 return &str[1];
50 else
51 return str;
52 }
53
54 struct timestamp {
55 int64_t real_timestamp; /* Relative to UNIX epoch. */
56 uint64_t clock_value; /* In cycles. */
57 };
58
59 static
60 enum bt_component_status print_field(struct text_component *text,
61 struct bt_ctf_field *field, bool print_names);
62
63 static
64 void print_timestamp_cycles(struct text_component *text,
65 struct bt_ctf_clock *clock,
66 struct bt_ctf_event *event)
67 {
68 int ret;
69 struct bt_ctf_clock_value *clock_value;
70 uint64_t cycles;
71
72 clock_value = bt_ctf_event_get_clock_value(event, clock);
73 if (!clock_value) {
74 fputs("????????????????????", text->out);
75 return;
76 }
77
78 ret = bt_ctf_clock_value_get_value(clock_value, &cycles);
79 bt_put(clock_value);
80 if (ret) {
81 fprintf(text->out, "Error");
82 return;
83 }
84 fprintf(text->out, "%020" PRIu64, cycles);
85 }
86
87 static
88 void print_timestamp_wall(struct text_component *text,
89 struct bt_ctf_clock *clock,
90 struct bt_ctf_event *event)
91 {
92 int ret;
93 struct bt_ctf_clock_value *clock_value;
94 int64_t ts_nsec = 0; /* add configurable offset */
95 int64_t ts_sec = 0; /* add configurable offset */
96 uint64_t ts_sec_abs, ts_nsec_abs;
97 bool is_negative;
98
99 clock_value = bt_ctf_event_get_clock_value(event, clock);
100 if (!clock_value) {
101 fputs("??:??:??.?????????", text->out);
102 return;
103 }
104
105 ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec);
106 bt_put(clock_value);
107 if (ret) {
108 fprintf(text->out, "Error");
109 return;
110 }
111
112 ts_sec += ts_nsec / NSEC_PER_SEC;
113 ts_nsec = ts_nsec % NSEC_PER_SEC;
114 if (ts_sec >= 0 && ts_nsec >= 0) {
115 is_negative = false;
116 ts_sec_abs = ts_sec;
117 ts_nsec_abs = ts_nsec;
118 } else if (ts_sec > 0 && ts_nsec < 0) {
119 is_negative = false;
120 ts_sec_abs = ts_sec - 1;
121 ts_nsec_abs = NSEC_PER_SEC + ts_nsec;
122 } else if (ts_sec == 0 && ts_nsec < 0) {
123 is_negative = true;
124 ts_sec_abs = ts_sec;
125 ts_nsec_abs = -ts_nsec;
126 } else if (ts_sec < 0 && ts_nsec > 0) {
127 is_negative = true;
128 ts_sec_abs = -(ts_sec + 1);
129 ts_nsec_abs = NSEC_PER_SEC - ts_nsec;
130 } else if (ts_sec < 0 && ts_nsec == 0) {
131 is_negative = true;
132 ts_sec_abs = -ts_sec;
133 ts_nsec_abs = ts_nsec;
134 } else { /* (ts_sec < 0 && ts_nsec < 0) */
135 is_negative = true;
136 ts_sec_abs = -ts_sec;
137 ts_nsec_abs = -ts_nsec;
138 }
139
140 if (!text->options.clock_seconds) {
141 struct tm tm;
142 time_t time_s = (time_t) ts_sec_abs;
143
144 if (is_negative) {
145 fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
146 goto seconds;
147 }
148
149 if (!text->options.clock_gmt) {
150 struct tm *res;
151
152 res = localtime_r(&time_s, &tm);
153 if (!res) {
154 fprintf(stderr, "[warning] Unable to get localtime.\n");
155 goto seconds;
156 }
157 } else {
158 struct tm *res;
159
160 res = gmtime_r(&time_s, &tm);
161 if (!res) {
162 fprintf(stderr, "[warning] Unable to get gmtime.\n");
163 goto seconds;
164 }
165 }
166 if (text->options.clock_date) {
167 char timestr[26];
168 size_t res;
169
170 /* Print date and time */
171 res = strftime(timestr, sizeof(timestr),
172 "%F ", &tm);
173 if (!res) {
174 fprintf(stderr, "[warning] Unable to print ascii time.\n");
175 goto seconds;
176 }
177 fprintf(text->out, "%s", timestr);
178 }
179 /* Print time in HH:MM:SS.ns */
180 fprintf(text->out, "%02d:%02d:%02d.%09" PRIu64,
181 tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec_abs);
182 goto end;
183 }
184 seconds:
185 fprintf(text->out, "%s%" PRId64 ".%09" PRIu64,
186 is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs);
187 end:
188 return;
189 }
190
191 static
192 enum bt_component_status print_event_timestamp(struct text_component *text,
193 struct bt_ctf_event *event, bool *start_line)
194 {
195 bool print_names = text->options.print_header_field_names;
196 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
197 struct bt_ctf_stream *stream = NULL;
198 struct bt_ctf_stream_class *stream_class = NULL;
199 struct bt_ctf_trace *trace = NULL;
200 struct bt_ctf_clock *clock = NULL;
201 FILE *out = text->out;
202 FILE *err = text->err;
203 uint64_t real_timestamp;
204
205 stream = bt_ctf_event_get_stream(event);
206 if (!stream) {
207 ret = BT_COMPONENT_STATUS_ERROR;
208 goto end;
209 }
210
211 stream_class = bt_ctf_stream_get_class(stream);
212 if (!stream_class) {
213 ret = BT_COMPONENT_STATUS_ERROR;
214 goto end;
215 }
216 trace = bt_ctf_stream_class_get_trace(stream_class);
217 if (!trace) {
218 ret = BT_COMPONENT_STATUS_ERROR;
219 goto end;
220 }
221 clock = bt_ctf_trace_get_clock(trace, 0);
222 if (!clock) {
223 ret = BT_COMPONENT_STATUS_ERROR;
224 goto end;
225 }
226
227 fputs(print_names ? "timestamp = " : "[", out);
228 if (text->options.print_timestamp_cycles) {
229 print_timestamp_cycles(text, clock, event);
230 } else {
231 print_timestamp_wall(text, clock, event);
232 }
233
234 if (!print_names)
235 fputs("] ", out);
236 *start_line = !print_names;
237
238 if (!text->options.print_delta_field) {
239 goto end;
240 }
241
242 //TODO delta
243
244 end:
245 bt_put(stream);
246 bt_put(clock);
247 bt_put(stream_class);
248 bt_put(trace);
249 return ret;
250 }
251
252 static
253 enum bt_component_status print_event_header(struct text_component *text,
254 struct bt_ctf_event *event)
255 {
256 bool print_names = text->options.print_header_field_names;
257 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
258 struct bt_ctf_event_class *event_class = NULL;
259 struct bt_ctf_stream_class *stream_class = NULL;
260 struct bt_ctf_trace *trace_class = NULL;
261
262 event_class = bt_ctf_event_get_class(event);
263 if (!event_class) {
264 ret = BT_COMPONENT_STATUS_ERROR;
265 goto end;
266 }
267 stream_class = bt_ctf_event_class_get_stream_class(event_class);
268 if (!stream_class) {
269 ret = BT_COMPONENT_STATUS_ERROR;
270 goto end;
271 }
272 trace_class = bt_ctf_stream_class_get_trace(stream_class);
273 if (!trace_class) {
274 ret = BT_COMPONENT_STATUS_ERROR;
275 goto end;
276 }
277 if (!text->start_line) {
278 fputs(", ", text->out);
279 }
280 text->start_line = false;
281 ret = print_event_timestamp(text, event, &text->start_line);
282 if (ret != BT_COMPONENT_STATUS_OK) {
283 goto end;
284 }
285 if (text->options.print_trace_field) {
286 const char *name;
287
288 name = bt_ctf_trace_get_name(trace_class);
289 if (name) {
290 if (!text->start_line) {
291 fputs(", ", text->out);
292 }
293 text->start_line = false;
294 if (print_names) {
295 fputs("trace = ", text->out);
296 }
297 fprintf(text->out, "%s", name);
298 }
299 }
300 if (text->options.print_trace_hostname_field) {
301 struct bt_value *hostname_str;
302
303 hostname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
304 "hostname");
305 if (hostname_str) {
306 const char *str;
307
308 if (!text->start_line) {
309 fputs(", ", text->out);
310 }
311 text->start_line = false;
312 if (print_names) {
313 fputs("trace:hostname = ", text->out);
314 }
315 if (bt_value_string_get(hostname_str, &str)
316 == BT_VALUE_STATUS_OK) {
317 fprintf(text->out, "%s", str);
318 }
319 bt_put(hostname_str);
320 }
321 }
322 if (text->options.print_trace_domain_field) {
323 struct bt_value *domain_str;
324
325 domain_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
326 "domain");
327 if (domain_str) {
328 const char *str;
329
330 if (!text->start_line) {
331 fputs(", ", text->out);
332 }
333 text->start_line = false;
334 if (print_names) {
335 fputs("trace:domain = ", text->out);
336 }
337 if (bt_value_string_get(domain_str, &str)
338 == BT_VALUE_STATUS_OK) {
339 fprintf(text->out, "%s", str);
340 }
341 bt_put(domain_str);
342 }
343 }
344 if (text->options.print_trace_procname_field) {
345 struct bt_value *procname_str;
346
347 procname_str = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
348 "procname");
349 if (procname_str) {
350 const char *str;
351
352 if (!text->start_line) {
353 fputs(", ", text->out);
354 }
355 text->start_line = false;
356 if (print_names) {
357 fputs("trace:procname = ", text->out);
358 }
359 if (bt_value_string_get(procname_str, &str)
360 == BT_VALUE_STATUS_OK) {
361 fprintf(text->out, "%s", str);
362 }
363 bt_put(procname_str);
364 }
365 }
366 if (text->options.print_trace_vpid_field) {
367 struct bt_value *vpid_value;
368
369 vpid_value = bt_ctf_trace_get_environment_field_value_by_name(trace_class,
370 "vpid");
371 if (vpid_value) {
372 int64_t value;
373
374 if (!text->start_line) {
375 fputs(", ", text->out);
376 }
377 text->start_line = false;
378 if (print_names) {
379 fputs("trace:vpid = ", text->out);
380 }
381 if (bt_value_integer_get(vpid_value, &value)
382 == BT_VALUE_STATUS_OK) {
383 fprintf(text->out, "(%" PRId64 ")", value);
384 }
385 bt_put(vpid_value);
386 }
387 }
388 if (text->options.print_loglevel_field) {
389 struct bt_value *loglevel_str, *loglevel_value;
390
391 loglevel_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
392 "loglevel_string");
393 loglevel_value = bt_ctf_event_class_get_attribute_value_by_name(event_class,
394 "loglevel");
395 if (loglevel_str || loglevel_value) {
396 bool has_str = false;
397
398 if (!text->start_line) {
399 fputs(", ", text->out);
400 }
401 text->start_line = false;
402 if (print_names) {
403 fputs("loglevel = ", text->out);
404 }
405 if (loglevel_str) {
406 const char *str;
407
408 if (bt_value_string_get(loglevel_str, &str)
409 == BT_VALUE_STATUS_OK) {
410 fprintf(text->out, "%s", str);
411 has_str = true;
412 }
413 }
414 if (loglevel_value) {
415 int64_t value;
416
417 if (bt_value_integer_get(loglevel_value, &value)
418 == BT_VALUE_STATUS_OK) {
419 fprintf(text->out, "%s(%" PRId64 ")",
420 has_str ? " " : "", value);
421 }
422 }
423 bt_put(loglevel_str);
424 bt_put(loglevel_value);
425 }
426 }
427 if (text->options.print_emf_field) {
428 struct bt_value *uri_str;
429
430 uri_str = bt_ctf_event_class_get_attribute_value_by_name(event_class,
431 "model.emf.uri");
432 if (uri_str) {
433 if (!text->start_line) {
434 fputs(", ", text->out);
435 }
436 text->start_line = false;
437 if (print_names) {
438 fputs("model.emf.uri = ", text->out);
439 }
440 if (uri_str) {
441 const char *str;
442
443 if (bt_value_string_get(uri_str, &str)
444 == BT_VALUE_STATUS_OK) {
445 fprintf(text->out, "%s", str);
446 }
447 }
448 bt_put(uri_str);
449 }
450 }
451 if (!text->start_line) {
452 fputs(", ", text->out);
453 }
454 text->start_line = false;
455 if (print_names) {
456 fputs("name = ", text->out);
457 }
458 fputs(bt_ctf_event_class_get_name(event_class), text->out);
459 end:
460 bt_put(trace_class);
461 bt_put(stream_class);
462 bt_put(event_class);
463 return ret;
464 }
465
466 static
467 enum bt_component_status print_integer(struct text_component *text,
468 struct bt_ctf_field *field)
469 {
470 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
471 struct bt_ctf_field_type *field_type = NULL;
472 enum bt_ctf_integer_base base;
473 enum bt_ctf_string_encoding encoding;
474 int signedness;
475 union {
476 uint64_t u;
477 int64_t s;
478 } v;
479
480 field_type = bt_ctf_field_get_type(field);
481 if (!field_type) {
482 ret = BT_COMPONENT_STATUS_ERROR;
483 goto end;
484 }
485 signedness = bt_ctf_field_type_integer_get_signed(field_type);
486 if (signedness < 0) {
487 ret = BT_COMPONENT_STATUS_ERROR;
488 goto end;
489 }
490 if (!signedness) {
491 if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) {
492 ret = BT_COMPONENT_STATUS_ERROR;
493 goto end;
494 }
495 } else {
496 if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) {
497 ret = BT_COMPONENT_STATUS_ERROR;
498 goto end;
499 }
500 }
501
502 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
503 switch (encoding) {
504 case BT_CTF_STRING_ENCODING_UTF8:
505 case BT_CTF_STRING_ENCODING_ASCII:
506 g_string_append_c(text->string, (int) v.u);
507 goto end;
508 case BT_CTF_STRING_ENCODING_NONE:
509 case BT_CTF_STRING_ENCODING_UNKNOWN:
510 break;
511 default:
512 ret = BT_COMPONENT_STATUS_ERROR;
513 goto end;
514 }
515
516 base = bt_ctf_field_type_integer_get_base(field_type);
517 switch (base) {
518 case BT_CTF_INTEGER_BASE_BINARY:
519 {
520 int bitnr, len;
521
522 len = bt_ctf_field_type_integer_get_size(field_type);
523 if (len < 0) {
524 ret = BT_COMPONENT_STATUS_ERROR;
525 goto end;
526 }
527 fprintf(text->out, "0b");
528 v.u = _bt_piecewise_lshift(v.u, 64 - len);
529 for (bitnr = 0; bitnr < len; bitnr++) {
530 fprintf(text->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0);
531 v.u = _bt_piecewise_lshift(v.u, 1);
532 }
533 break;
534 }
535 case BT_CTF_INTEGER_BASE_OCTAL:
536 {
537 if (signedness) {
538 int len;
539
540 len = bt_ctf_field_type_integer_get_size(field_type);
541 if (len < 0) {
542 ret = BT_COMPONENT_STATUS_ERROR;
543 goto end;
544 }
545 if (len < 64) {
546 size_t rounded_len;
547
548 assert(len != 0);
549 /* Round length to the nearest 3-bit */
550 rounded_len = (((len - 1) / 3) + 1) * 3;
551 v.u &= ((uint64_t) 1 << rounded_len) - 1;
552 }
553 }
554
555 fprintf(text->out, "0%" PRIo64, v.u);
556 break;
557 }
558 case BT_CTF_INTEGER_BASE_DECIMAL:
559 if (!signedness) {
560 fprintf(text->out, "%" PRIu64, v.u);
561 } else {
562 fprintf(text->out, "%" PRId64, v.s);
563 }
564 break;
565 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
566 {
567 int len;
568
569 len = bt_ctf_field_type_integer_get_size(field_type);
570 if (len < 0) {
571 ret = BT_COMPONENT_STATUS_ERROR;
572 goto end;
573 }
574 if (len < 64) {
575 /* Round length to the nearest nibble */
576 uint8_t rounded_len = ((len + 3) & ~0x3);
577
578 v.u &= ((uint64_t) 1 << rounded_len) - 1;
579 }
580
581 fprintf(text->out, "0x%" PRIX64, v.u);
582 break;
583 }
584 default:
585 ret = BT_COMPONENT_STATUS_ERROR;
586 goto end;
587 }
588 end:
589 bt_put(field_type);
590 return ret;
591 }
592
593 static
594 enum bt_component_status print_enum(struct text_component *text,
595 struct bt_ctf_field *field)
596 {
597 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
598 struct bt_ctf_field *container_field = NULL;
599 const char *mapping_name;
600
601 container_field = bt_ctf_field_enumeration_get_container(field);
602 if (!container_field) {
603 ret = BT_COMPONENT_STATUS_ERROR;
604 goto end;
605 }
606 mapping_name = bt_ctf_field_enumeration_get_mapping_name(field);
607 if (mapping_name) {
608 fprintf(text->out, "( \"%s\"", mapping_name);
609 } else {
610 fprintf(text->out, "( <unknown>");
611 }
612 fprintf(text->out, " : container = ");
613 ret = print_integer(text, container_field);
614 if (ret != BT_COMPONENT_STATUS_OK) {
615 goto end;
616 }
617 fprintf(text->out, " )");
618 end:
619 bt_put(container_field);
620 return ret;
621 }
622
623 static
624 enum bt_component_status print_struct_field(struct text_component *text,
625 struct bt_ctf_field *_struct,
626 struct bt_ctf_field_type *struct_type,
627 int i, bool print_names)
628 {
629 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
630 const char *field_name;
631 struct bt_ctf_field *field = NULL;
632 struct bt_ctf_field_type *field_type = NULL;;
633
634 field = bt_ctf_field_structure_get_field_by_index(_struct, i);
635 if (!field) {
636 ret = BT_COMPONENT_STATUS_ERROR;
637 goto end;
638 }
639 if (bt_ctf_field_type_structure_get_field(struct_type,
640 &field_name, &field_type, i) < 0) {
641 ret = BT_COMPONENT_STATUS_ERROR;
642 goto end;
643 }
644
645 if (i != 0) {
646 fprintf(text->out, ", ");
647 } else {
648 fprintf(text->out, " ");
649 }
650 if (print_names) {
651 fprintf(text->out, "%s = ", rem_(field_name));
652 }
653 ret = print_field(text, field, print_names);
654 end:
655 bt_put(field_type);
656 bt_put(field);
657 return ret;
658 }
659
660 static
661 enum bt_component_status print_struct(struct text_component *text,
662 struct bt_ctf_field *_struct, bool print_names)
663 {
664 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
665 struct bt_ctf_field_type *struct_type = NULL;
666 int nr_fields, i;
667
668 struct_type = bt_ctf_field_get_type(_struct);
669 if (!struct_type) {
670 ret = BT_COMPONENT_STATUS_ERROR;
671 goto end;
672 }
673 nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type);
674 if (nr_fields < 0) {
675 ret = BT_COMPONENT_STATUS_ERROR;
676 goto end;
677 }
678 fprintf(text->out, "{");
679 text->depth++;
680 for (i = 0; i < nr_fields; i++) {
681 ret = print_struct_field(text, _struct, struct_type, i,
682 print_names);
683 if (ret != BT_COMPONENT_STATUS_OK) {
684 goto end;
685 }
686 }
687 text->depth--;
688 fprintf(text->out, " }");
689 end:
690 bt_put(struct_type);
691 return ret;
692 }
693
694 static
695 enum bt_component_status print_array_field(struct text_component *text,
696 struct bt_ctf_field *array, uint64_t i,
697 bool is_string, bool print_names)
698 {
699 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
700 struct bt_ctf_field *field = NULL;
701
702 if (!is_string) {
703 if (i != 0) {
704 fprintf(text->out, ", ");
705 } else {
706 fprintf(text->out, " ");
707 }
708 }
709 field = bt_ctf_field_array_get_field(array, i);
710 if (!field) {
711 ret = BT_COMPONENT_STATUS_ERROR;
712 goto end;
713 }
714 ret = print_field(text, field, print_names);
715 end:
716 bt_put(field);
717 return ret;
718 }
719
720 static
721 enum bt_component_status print_array(struct text_component *text,
722 struct bt_ctf_field *array, bool print_names)
723 {
724 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
725 struct bt_ctf_field_type *array_type = NULL, *field_type = NULL;
726 enum bt_ctf_type_id type_id;
727 int64_t len;
728 uint64_t i;
729 bool is_string = false;
730
731 array_type = bt_ctf_field_get_type(array);
732 if (!array_type) {
733 ret = BT_COMPONENT_STATUS_ERROR;
734 goto end;
735 }
736 field_type = bt_ctf_field_type_array_get_element_type(array_type);
737 if (!field_type) {
738 ret = BT_COMPONENT_STATUS_ERROR;
739 goto end;
740 }
741 len = bt_ctf_field_type_array_get_length(array_type);
742 if (len < 0) {
743 ret = BT_COMPONENT_STATUS_ERROR;
744 goto end;
745 }
746 type_id = bt_ctf_field_type_get_type_id(field_type);
747 if (type_id == BT_CTF_TYPE_ID_INTEGER) {
748 enum bt_ctf_string_encoding encoding;
749
750 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
751 if (encoding == BT_CTF_STRING_ENCODING_UTF8
752 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
753 int integer_len, integer_alignment;
754
755 integer_len = bt_ctf_field_type_integer_get_size(field_type);
756 if (integer_len < 0) {
757 return BT_COMPONENT_STATUS_ERROR;
758 }
759 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
760 if (integer_alignment < 0) {
761 return BT_COMPONENT_STATUS_ERROR;
762 }
763 if (integer_len == CHAR_BIT
764 && integer_alignment == CHAR_BIT) {
765 is_string = true;
766 }
767 }
768 }
769
770 if (is_string) {
771 g_string_assign(text->string, "");
772 } else {
773 fprintf(text->out, "[");
774 }
775
776 text->depth++;
777 for (i = 0; i < len; i++) {
778 ret = print_array_field(text, array, i, is_string, print_names);
779 if (ret != BT_COMPONENT_STATUS_OK) {
780 goto end;
781 }
782 }
783 text->depth--;
784
785 if (is_string) {
786 fprintf(text->out, "\"%s\"", text->string->str);
787 } else {
788 fprintf(text->out, " ]");
789 }
790 end:
791 bt_put(field_type);
792 bt_put(array_type);
793 return ret;
794 }
795
796 static
797 enum bt_component_status print_sequence_field(struct text_component *text,
798 struct bt_ctf_field *seq, uint64_t i,
799 bool is_string, bool print_names)
800 {
801 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
802 struct bt_ctf_field *field = NULL;
803
804 if (!is_string) {
805 if (i != 0) {
806 fprintf(text->out, ", ");
807 } else {
808 fprintf(text->out, " ");
809 }
810 }
811 field = bt_ctf_field_sequence_get_field(seq, i);
812 if (!field) {
813 ret = BT_COMPONENT_STATUS_ERROR;
814 goto end;
815 }
816 ret = print_field(text, field, print_names);
817 end:
818 bt_put(field);
819 return ret;
820 }
821
822 static
823 enum bt_component_status print_sequence(struct text_component *text,
824 struct bt_ctf_field *seq, bool print_names)
825 {
826 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
827 struct bt_ctf_field_type *seq_type = NULL, *field_type = NULL;
828 struct bt_ctf_field *length_field = NULL;
829 enum bt_ctf_type_id type_id;
830 uint64_t len;
831 uint64_t i;
832 bool is_string = false;
833
834 seq_type = bt_ctf_field_get_type(seq);
835 if (!seq_type) {
836 ret = BT_COMPONENT_STATUS_ERROR;
837 goto end;
838 }
839 length_field = bt_ctf_field_sequence_get_length(seq);
840 if (!length_field) {
841 ret = BT_COMPONENT_STATUS_ERROR;
842 goto end;
843 }
844 if (bt_ctf_field_unsigned_integer_get_value(length_field, &len) < 0) {
845 ret = BT_COMPONENT_STATUS_ERROR;
846 goto end;
847 }
848 field_type = bt_ctf_field_type_sequence_get_element_type(seq_type);
849 if (!field_type) {
850 ret = BT_COMPONENT_STATUS_ERROR;
851 goto end;
852 }
853 type_id = bt_ctf_field_type_get_type_id(field_type);
854 if (type_id == BT_CTF_TYPE_ID_INTEGER) {
855 enum bt_ctf_string_encoding encoding;
856
857 encoding = bt_ctf_field_type_integer_get_encoding(field_type);
858 if (encoding == BT_CTF_STRING_ENCODING_UTF8
859 || encoding == BT_CTF_STRING_ENCODING_ASCII) {
860 int integer_len, integer_alignment;
861
862 integer_len = bt_ctf_field_type_integer_get_size(field_type);
863 if (integer_len < 0) {
864 ret = BT_COMPONENT_STATUS_ERROR;
865 goto end;
866 }
867 integer_alignment = bt_ctf_field_type_get_alignment(field_type);
868 if (integer_alignment < 0) {
869 ret = BT_COMPONENT_STATUS_ERROR;
870 goto end;
871 }
872 if (integer_len == CHAR_BIT
873 && integer_alignment == CHAR_BIT) {
874 is_string = true;
875 }
876 }
877 }
878
879 if (is_string) {
880 g_string_assign(text->string, "");
881 } else {
882 fprintf(text->out, "[");
883 }
884
885 text->depth++;
886 for (i = 0; i < len; i++) {
887 ret = print_sequence_field(text, seq, i,
888 is_string, print_names);
889 if (ret != BT_COMPONENT_STATUS_OK) {
890 goto end;
891 }
892 }
893 text->depth--;
894
895 if (is_string) {
896 fprintf(text->out, "\"%s\"", text->string->str);
897 } else {
898 fprintf(text->out, " ]");
899 }
900 end:
901 bt_put(length_field);
902 bt_put(field_type);
903 bt_put(seq_type);
904 return ret;
905 }
906
907 static
908 enum bt_component_status print_variant(struct text_component *text,
909 struct bt_ctf_field *variant, bool print_names)
910 {
911 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
912 struct bt_ctf_field *field = NULL;
913
914 field = bt_ctf_field_variant_get_current_field(variant);
915 if (!field) {
916 ret = BT_COMPONENT_STATUS_ERROR;
917 goto end;
918 }
919 fprintf(text->out, "{ ");
920 text->depth++;
921 if (print_names) {
922 struct bt_ctf_field *tag_field = NULL;
923 const char *tag_choice;
924
925 tag_field = bt_ctf_field_variant_get_tag(variant);
926 if (!tag_field) {
927 ret = BT_COMPONENT_STATUS_ERROR;
928 goto end;
929 }
930 tag_choice = bt_ctf_field_enumeration_get_mapping_name(tag_field);
931 if (!tag_choice) {
932 bt_put(tag_field);
933 ret = BT_COMPONENT_STATUS_ERROR;
934 goto end;
935 }
936 fprintf(text->out, "%s = ", rem_(tag_choice));
937 bt_put(tag_field);
938 }
939 ret = print_field(text, field, print_names);
940 if (ret != BT_COMPONENT_STATUS_OK) {
941 goto end;
942 }
943 text->depth--;
944 fprintf(text->out, " }");
945 end:
946 bt_put(field);
947 return ret;
948 }
949
950 static
951 enum bt_component_status print_field(struct text_component *text,
952 struct bt_ctf_field *field, bool print_names)
953 {
954 enum bt_ctf_type_id type_id;
955
956 type_id = bt_ctf_field_get_type_id(field);
957 switch (type_id) {
958 case CTF_TYPE_INTEGER:
959 return print_integer(text, field);
960 case CTF_TYPE_FLOAT:
961 {
962 double v;
963
964 if (bt_ctf_field_floating_point_get_value(field, &v)) {
965 return BT_COMPONENT_STATUS_ERROR;
966 }
967 fprintf(text->out, "%g", v);
968 return BT_COMPONENT_STATUS_OK;
969 }
970 case CTF_TYPE_ENUM:
971 return print_enum(text, field);
972 case CTF_TYPE_STRING:
973 fprintf(text->out, "\"%s\"", bt_ctf_field_string_get_value(field));
974 return BT_COMPONENT_STATUS_OK;
975 case CTF_TYPE_STRUCT:
976 return print_struct(text, field, print_names);
977 case CTF_TYPE_UNTAGGED_VARIANT:
978 case CTF_TYPE_VARIANT:
979 return print_variant(text, field, print_names);
980 case CTF_TYPE_ARRAY:
981 return print_array(text, field, print_names);
982 case CTF_TYPE_SEQUENCE:
983 return print_sequence(text, field, print_names);
984 default:
985 fprintf(text->err, "[error] Unknown type id: %d\n", (int) type_id);
986 return BT_COMPONENT_STATUS_ERROR;
987 }
988 }
989
990 static
991 enum bt_component_status print_stream_packet_context(struct text_component *text,
992 struct bt_ctf_event *event)
993 {
994 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
995 struct bt_ctf_packet *packet = NULL;
996 struct bt_ctf_field *main_field = NULL;
997
998 packet = bt_ctf_event_get_packet(event);
999 if (!packet) {
1000 ret = BT_COMPONENT_STATUS_ERROR;
1001 goto end;
1002 }
1003 main_field = bt_ctf_packet_get_context(packet);
1004 if (!main_field) {
1005 ret = BT_COMPONENT_STATUS_ERROR;
1006 goto end;
1007 }
1008 if (!text->start_line) {
1009 fputs(", ", text->out);
1010 }
1011 text->start_line = false;
1012 if (text->options.print_scope_field_names) {
1013 fputs("stream.packet.context = ", text->out);
1014 }
1015 ret = print_field(text, main_field,
1016 text->options.print_context_field_names);
1017 end:
1018 bt_put(main_field);
1019 bt_put(packet);
1020 return ret;
1021 }
1022
1023 static
1024 enum bt_component_status print_event_header_raw(struct text_component *text,
1025 struct bt_ctf_event *event)
1026 {
1027 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1028 struct bt_ctf_field *main_field = NULL;
1029
1030 main_field = bt_ctf_event_get_header(event);
1031 if (!main_field) {
1032 ret = BT_COMPONENT_STATUS_ERROR;
1033 goto end;
1034 }
1035 if (!text->start_line) {
1036 fputs(", ", text->out);
1037 }
1038 text->start_line = false;
1039 if (text->options.print_scope_field_names) {
1040 fputs("stream.event.header = ", text->out);
1041 }
1042 ret = print_field(text, main_field,
1043 text->options.print_header_field_names);
1044 end:
1045 bt_put(main_field);
1046 return ret;
1047 }
1048
1049 static
1050 enum bt_component_status print_stream_event_context(struct text_component *text,
1051 struct bt_ctf_event *event)
1052 {
1053 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1054 struct bt_ctf_field *main_field = NULL;
1055
1056 main_field = bt_ctf_event_get_stream_event_context(event);
1057 if (!main_field) {
1058 ret = BT_COMPONENT_STATUS_ERROR;
1059 goto end;
1060 }
1061 if (!text->start_line) {
1062 fputs(", ", text->out);
1063 }
1064 text->start_line = false;
1065 if (text->options.print_scope_field_names) {
1066 fputs("stream.event.context = ", text->out);
1067 }
1068 ret = print_field(text, main_field,
1069 text->options.print_context_field_names);
1070 end:
1071 bt_put(main_field);
1072 return ret;
1073 }
1074
1075 static
1076 enum bt_component_status print_event_context(struct text_component *text,
1077 struct bt_ctf_event *event)
1078 {
1079 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1080 struct bt_ctf_field *main_field = NULL;
1081
1082 main_field = bt_ctf_event_get_event_context(event);
1083 if (!main_field) {
1084 ret = BT_COMPONENT_STATUS_ERROR;
1085 goto end;
1086 }
1087 if (!text->start_line) {
1088 fputs(", ", text->out);
1089 }
1090 text->start_line = false;
1091 if (text->options.print_scope_field_names) {
1092 fputs("event.context = ", text->out);
1093 }
1094 ret = print_field(text, main_field,
1095 text->options.print_context_field_names);
1096 end:
1097 bt_put(main_field);
1098 return ret;
1099 }
1100
1101 static
1102 enum bt_component_status print_event_payload(struct text_component *text,
1103 struct bt_ctf_event *event)
1104 {
1105 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
1106 struct bt_ctf_field *main_field = NULL;
1107
1108 main_field = bt_ctf_event_get_payload_field(event);
1109 if (!main_field) {
1110 ret = BT_COMPONENT_STATUS_ERROR;
1111 goto end;
1112 }
1113 if (!text->start_line) {
1114 fputs(", ", text->out);
1115 }
1116 text->start_line = false;
1117 if (text->options.print_scope_field_names) {
1118 fputs("event.fields = ", text->out);
1119 }
1120 ret = print_field(text, main_field,
1121 text->options.print_payload_field_names);
1122 end:
1123 bt_put(main_field);
1124 return ret;
1125 }
1126
1127 BT_HIDDEN
1128 enum bt_component_status text_print_event(struct text_component *text,
1129 struct bt_ctf_event *event)
1130 {
1131 enum bt_component_status ret;
1132
1133 text->start_line = true;
1134 ret = print_event_header(text, event);
1135 if (ret != BT_COMPONENT_STATUS_OK) {
1136 goto end;
1137 }
1138
1139 ret = print_stream_packet_context(text, event);
1140 if (ret != BT_COMPONENT_STATUS_OK) {
1141 goto end;
1142 }
1143
1144 ret = print_event_header_raw(text, event);
1145 if (ret != BT_COMPONENT_STATUS_OK) {
1146 goto end;
1147 }
1148
1149 ret = print_stream_event_context(text, event);
1150 if (ret != BT_COMPONENT_STATUS_OK) {
1151 goto end;
1152 }
1153
1154 ret = print_event_context(text, event);
1155 if (ret != BT_COMPONENT_STATUS_OK) {
1156 goto end;
1157 }
1158
1159 ret = print_event_payload(text, event);
1160 if (ret != BT_COMPONENT_STATUS_OK) {
1161 goto end;
1162 }
1163
1164 fputc('\n', text->out);
1165 end:
1166 return ret;
1167 }
This page took 0.058499 seconds and 4 git commands to generate.