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