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