plugins/ctf/common/btr: use standard logging files and macros
[babeltrace.git] / plugins / ctf / common / btr / btr.c
1 /*
2 * Babeltrace - CTF binary type reader (BTR)
3 *
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #define BT_LOG_TAG "PLUGIN-CTF-BTR"
27 #include "logging.h"
28
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <inttypes.h>
32 #include <stdio.h>
33 #include <stddef.h>
34 #include <stdbool.h>
35 #include <assert.h>
36 #include <string.h>
37 #include <babeltrace/bitfield-internal.h>
38 #include <babeltrace/ctf-ir/field-types.h>
39 #include <babeltrace/ctf-ir/field-types-internal.h>
40 #include <babeltrace/ref.h>
41 #include <babeltrace/align-internal.h>
42 #include <glib.h>
43
44 #include "btr.h"
45
46 #define PRINT_ERR_STREAM (btr ? btr->err_stream : stderr)
47 #define PRINT_PREFIX "ctf-btr"
48 #include "../print.h"
49
50 #define DIV8(_x) ((_x) >> 3)
51 #define BYTES_TO_BITS(_x) ((_x) * 8)
52 #define BITS_TO_BYTES_FLOOR(_x) DIV8(_x)
53 #define BITS_TO_BYTES_CEIL(_x) DIV8((_x) + 7)
54 #define IN_BYTE_OFFSET(_at) ((_at) & 7)
55
56 /* A visit stack entry */
57 struct stack_entry {
58 /*
59 * Current type of base field, one of:
60 *
61 * * Structure
62 * * Array
63 * * Sequence
64 * * Variant
65 *
66 * Owned by this.
67 */
68 struct bt_ctf_field_type *base_type;
69
70 /* Length of base field (always 1 for variant types) */
71 int64_t base_len;
72
73 /* Lndex of next field to read */
74 int64_t index;
75 };
76
77 /* Visit stack */
78 struct stack {
79 /* Entries (struct stack_entry *) (top is last element) */
80 GPtrArray *entries;
81 };
82
83 /* Reading states */
84 enum btr_state {
85 BTR_STATE_NEXT_FIELD,
86 BTR_STATE_ALIGN_BASIC,
87 BTR_STATE_ALIGN_COMPOUND,
88 BTR_STATE_READ_BASIC_BEGIN,
89 BTR_STATE_READ_BASIC_CONTINUE,
90 BTR_STATE_DONE,
91 };
92
93 /* Binary type reader */
94 struct bt_ctf_btr {
95 /* Bisit stack */
96 struct stack *stack;
97
98 /* Error stream */
99 FILE *err_stream;
100
101 /* Current basic field type */
102 struct bt_ctf_field_type *cur_basic_field_type;
103
104 /* Current state */
105 enum btr_state state;
106
107 /*
108 * Last basic field type's byte order.
109 *
110 * This is used to detect errors since two contiguous basic
111 * types for which the common boundary is not the boundary of
112 * a byte cannot have different byte orders.
113 *
114 * This is set to BT_CTF_BYTE_ORDER_UNKNOWN on reset and when
115 * the last basic field type was a string type.
116 */
117 enum bt_ctf_byte_order last_bo;
118
119 /* Current byte order (copied to last_bo after a successful read) */
120 enum bt_ctf_byte_order cur_bo;
121
122 /* Stitch buffer infos */
123 struct {
124 /* Stitch buffer */
125 uint8_t buf[16];
126
127 /* Offset, within stitch buffer, of first bit */
128 size_t offset;
129
130 /* Length (bits) of data in stitch buffer from offset */
131 size_t at;
132 } stitch;
133
134 /* User buffer infos */
135 struct {
136 /* Address */
137 const uint8_t *addr;
138
139 /* Offset of data from address (bits) */
140 size_t offset;
141
142 /* Current position from offset (bits) */
143 size_t at;
144
145 /* Offset of offset within whole packet (bits) */
146 size_t packet_offset;
147
148 /* Data size in buffer (bits) */
149 size_t sz;
150
151 /* Buffer size (bytes) */
152 size_t buf_sz;
153 } buf;
154
155 /* User stuff */
156 struct {
157 /* Callback functions */
158 struct bt_ctf_btr_cbs cbs;
159
160 /* Private data */
161 void *data;
162 } user;
163 };
164
165 static inline
166 const char *btr_state_string(enum btr_state state)
167 {
168 switch (state) {
169 case BTR_STATE_NEXT_FIELD:
170 return "BTR_STATE_NEXT_FIELD";
171 case BTR_STATE_ALIGN_BASIC:
172 return "BTR_STATE_ALIGN_BASIC";
173 case BTR_STATE_ALIGN_COMPOUND:
174 return "BTR_STATE_ALIGN_COMPOUND";
175 case BTR_STATE_READ_BASIC_BEGIN:
176 return "BTR_STATE_READ_BASIC_BEGIN";
177 case BTR_STATE_READ_BASIC_CONTINUE:
178 return "BTR_STATE_READ_BASIC_CONTINUE";
179 case BTR_STATE_DONE:
180 return "BTR_STATE_DONE";
181 default:
182 return "(unknown)";
183 }
184 }
185
186 static
187 void stack_entry_free_func(gpointer data)
188 {
189 struct stack_entry *entry = data;
190
191 BT_PUT(entry->base_type);
192 g_free(entry);
193 }
194
195 static
196 struct stack *stack_new(void)
197 {
198 struct stack *stack = NULL;
199
200 stack = g_new0(struct stack, 1);
201 if (!stack) {
202 BT_LOGE_STR("Failed to allocate one stack.");
203 goto error;
204 }
205
206 stack->entries = g_ptr_array_new_with_free_func(stack_entry_free_func);
207 if (!stack->entries) {
208 BT_LOGE_STR("Failed to allocate a GPtrArray.");
209 goto error;
210 }
211
212 BT_LOGD("Created stack: addr=%p", stack);
213 return stack;
214
215 error:
216 g_free(stack);
217
218 return NULL;
219 }
220
221 static
222 void stack_destroy(struct stack *stack)
223 {
224 if (!stack) {
225 return;
226 }
227
228 BT_LOGD("Destroying stack: addr=%p", stack);
229 g_ptr_array_free(stack->entries, TRUE);
230 g_free(stack);
231 }
232
233 static inline
234 int64_t get_compound_field_type_length(struct bt_ctf_btr *btr,
235 struct bt_ctf_field_type *field_type)
236 {
237 int64_t length;
238
239 switch (bt_ctf_field_type_get_type_id(field_type)) {
240 case BT_CTF_FIELD_TYPE_ID_STRUCT:
241 length = (int64_t) bt_ctf_field_type_structure_get_field_count(
242 field_type);
243 break;
244 case BT_CTF_FIELD_TYPE_ID_VARIANT:
245 /* Variant field types always "contain" a single type */
246 length = 1;
247 break;
248 case BT_CTF_FIELD_TYPE_ID_ARRAY:
249 length = bt_ctf_field_type_array_get_length(field_type);
250 break;
251 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
252 length = btr->user.cbs.query.get_sequence_length(field_type,
253 btr->user.data);
254 break;
255 default:
256 BT_LOGW("Cannot get field type's field count: btr-addr=%p, "
257 "ft-addr=%p, ft-id=%s",
258 btr, field_type,
259 bt_ctf_field_type_id_string(
260 bt_ctf_field_type_get_type_id(field_type)));
261 length = BT_CTF_BTR_STATUS_ERROR;
262 }
263
264 return length;
265 }
266
267 static
268 int stack_push(struct stack *stack, struct bt_ctf_field_type *base_type,
269 size_t base_len)
270 {
271 int ret = 0;
272 struct stack_entry *entry;
273
274 assert(stack);
275 assert(base_type);
276
277 BT_LOGV("Pushing field type on stack: stack-addr=%p, "
278 "ft-addr=%p, ft-id=%s, base-length=%zu, "
279 "stack-size-before=%u, stack-size-after=%u",
280 stack, base_type, bt_ctf_field_type_id_string(
281 bt_ctf_field_type_get_type_id(base_type)),
282 base_len, stack->entries->len, stack->entries->len + 1);
283 entry = g_new0(struct stack_entry, 1);
284 if (!entry) {
285 BT_LOGE("Failed to allocate one stack entry: stack-addr=%p",
286 stack);
287 ret = BT_CTF_BTR_STATUS_ERROR;
288 goto end;
289 }
290
291 entry->base_type = base_type;
292 bt_get(entry->base_type);
293 entry->base_len = base_len;
294 g_ptr_array_add(stack->entries, entry);
295
296 end:
297 return ret;
298 }
299
300 static
301 int stack_push_with_len(struct bt_ctf_btr *btr,
302 struct bt_ctf_field_type *base_type)
303 {
304 int ret = 0;
305 int64_t base_len = get_compound_field_type_length(btr, base_type);
306
307 if (base_len < 0) {
308 BT_LOGW("Cannot get compound field type's field count: "
309 "btr-addr=%p, ft-addr=%p, ft-id=%s",
310 btr, base_type, bt_ctf_field_type_id_string(
311 bt_ctf_field_type_get_type_id(base_type)));
312 ret = BT_CTF_BTR_STATUS_ERROR;
313 goto end;
314 }
315
316 ret = stack_push(btr->stack, base_type, (size_t) base_len);
317
318 end:
319 return ret;
320 }
321
322 static inline
323 unsigned int stack_size(struct stack *stack)
324 {
325 assert(stack);
326
327 return stack->entries->len;
328 }
329
330 static
331 void stack_pop(struct stack *stack)
332 {
333 assert(stack);
334 assert(stack_size(stack));
335 BT_LOGV("Popping from stack: "
336 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
337 stack, stack->entries->len, stack->entries->len - 1);
338 g_ptr_array_remove_index(stack->entries, stack->entries->len - 1);
339 }
340
341 static inline
342 bool stack_empty(struct stack *stack)
343 {
344 return stack_size(stack) == 0;
345 }
346
347 static
348 void stack_clear(struct stack *stack)
349 {
350 assert(stack);
351
352 if (!stack_empty(stack)) {
353 g_ptr_array_remove_range(stack->entries, 0, stack_size(stack));
354 }
355
356 assert(stack_empty(stack));
357 }
358
359 static inline
360 struct stack_entry *stack_top(struct stack *stack)
361 {
362 assert(stack);
363 assert(stack_size(stack));
364
365 return g_ptr_array_index(stack->entries, stack->entries->len - 1);
366 }
367
368 static inline
369 size_t available_bits(struct bt_ctf_btr *btr)
370 {
371 return btr->buf.sz - btr->buf.at;
372 }
373
374 static inline
375 void consume_bits(struct bt_ctf_btr *btr, size_t incr)
376 {
377 BT_LOGV("Advancing cursor: btr-addr=%p, cur-before=%zu, cur-after=%zu",
378 btr, btr->buf.at, btr->buf.at + incr);
379 btr->buf.at += incr;
380 }
381
382 static inline
383 bool has_enough_bits(struct bt_ctf_btr *btr, size_t sz)
384 {
385 return available_bits(btr) >= sz;
386 }
387
388 static inline
389 bool at_least_one_bit_left(struct bt_ctf_btr *btr)
390 {
391 return has_enough_bits(btr, 1);
392 }
393
394 static inline
395 size_t packet_at(struct bt_ctf_btr *btr)
396 {
397 return btr->buf.packet_offset + btr->buf.at;
398 }
399
400 static inline
401 size_t buf_at_from_addr(struct bt_ctf_btr *btr)
402 {
403 /*
404 * Considering this:
405 *
406 * ====== offset ===== (17)
407 *
408 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
409 * ^
410 * addr (0) ==== at ==== (12)
411 *
412 * We want this:
413 *
414 * =============================== (29)
415 */
416 return btr->buf.offset + btr->buf.at;
417 }
418
419 static inline
420 int get_basic_field_type_size(struct bt_ctf_btr *btr,
421 struct bt_ctf_field_type *field_type)
422 {
423 int size;
424
425 switch (bt_ctf_field_type_get_type_id(field_type)) {
426 case BT_CTF_FIELD_TYPE_ID_INTEGER:
427 size = bt_ctf_field_type_integer_get_size(field_type);
428 break;
429 case BT_CTF_FIELD_TYPE_ID_FLOAT:
430 {
431 int exp_dig, mant_dig;
432
433 exp_dig =
434 bt_ctf_field_type_floating_point_get_exponent_digits(
435 field_type);
436 mant_dig =
437 bt_ctf_field_type_floating_point_get_mantissa_digits(
438 field_type);
439 assert(exp_dig >= 0);
440 assert(mant_dig >= 0);
441 size = exp_dig + mant_dig;
442 break;
443 }
444 case BT_CTF_FIELD_TYPE_ID_ENUM:
445 {
446 struct bt_ctf_field_type *int_type;
447
448 int_type = bt_ctf_field_type_enumeration_get_container_type(
449 field_type);
450 assert(int_type);
451 size = get_basic_field_type_size(btr, int_type);
452 BT_PUT(int_type);
453 break;
454 }
455 default:
456 size = BT_CTF_BTR_STATUS_ERROR;
457 break;
458 }
459
460 return size;
461 }
462
463 static
464 void stitch_reset(struct bt_ctf_btr *btr)
465 {
466 btr->stitch.offset = 0;
467 btr->stitch.at = 0;
468 }
469
470 static inline
471 size_t stitch_at_from_addr(struct bt_ctf_btr *btr)
472 {
473 return btr->stitch.offset + btr->stitch.at;
474 }
475
476 static
477 void stitch_append_from_buf(struct bt_ctf_btr *btr, size_t sz)
478 {
479 size_t stitch_byte_at;
480 size_t buf_byte_at;
481 size_t nb_bytes;;
482
483 if (sz == 0) {
484 return;
485 }
486
487 stitch_byte_at =
488 BITS_TO_BYTES_FLOOR(stitch_at_from_addr(btr));
489 buf_byte_at = BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr));
490 nb_bytes = BITS_TO_BYTES_CEIL(sz);
491 assert(nb_bytes > 0);
492 memcpy(&btr->stitch.buf[stitch_byte_at], &btr->buf.addr[buf_byte_at],
493 nb_bytes);
494 btr->stitch.at += sz;
495 consume_bits(btr, sz);
496 }
497
498 static
499 void stitch_append_from_remaining_buf(struct bt_ctf_btr *btr)
500 {
501 stitch_append_from_buf(btr, available_bits(btr));
502 }
503
504 static
505 void stitch_set_from_remaining_buf(struct bt_ctf_btr *btr)
506 {
507 stitch_reset(btr);
508 btr->stitch.offset = IN_BYTE_OFFSET(buf_at_from_addr(btr));
509 stitch_append_from_remaining_buf(btr);
510 }
511
512 static inline
513 enum bt_ctf_btr_status read_unsigned_bitfield(const uint8_t *buf, size_t at,
514 int64_t field_size, enum bt_ctf_byte_order bo, uint64_t *v)
515 {
516 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
517
518 switch (bo) {
519 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
520 case BT_CTF_BYTE_ORDER_NETWORK:
521 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
522 break;
523 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
524 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
525 break;
526 default:
527 BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo);
528 abort();
529 }
530
531 BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64 ", "
532 "bo=%s, val=%" PRIu64, at, field_size,
533 bt_ctf_byte_order_string(bo), *v);
534 return status;
535 }
536
537 static inline
538 enum bt_ctf_btr_status read_signed_bitfield(const uint8_t *buf, size_t at,
539 int64_t field_size, enum bt_ctf_byte_order bo, int64_t *v)
540 {
541 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
542
543 switch (bo) {
544 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
545 case BT_CTF_BYTE_ORDER_NETWORK:
546 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
547 break;
548 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
549 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
550 break;
551 default:
552 BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo);
553 abort();
554 }
555
556 BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64 ", "
557 "bo=%s, val=%" PRId64, at, field_size,
558 bt_ctf_byte_order_string(bo), *v);
559 return status;
560 }
561
562 typedef enum bt_ctf_btr_status (* read_basic_and_call_cb_t)(struct bt_ctf_btr *,
563 const uint8_t *, size_t);
564
565 static inline
566 enum bt_ctf_btr_status validate_contiguous_bo(struct bt_ctf_btr *btr,
567 enum bt_ctf_byte_order next_bo)
568 {
569 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
570
571 /* Always valid when at a byte boundary */
572 if (packet_at(btr) % 8 == 0) {
573 goto end;
574 }
575
576 /* Always valid if last byte order is unknown */
577 if (btr->last_bo == BT_CTF_BYTE_ORDER_UNKNOWN) {
578 goto end;
579 }
580
581 /* Always valid if next byte order is unknown */
582 if (next_bo == BT_CTF_BYTE_ORDER_UNKNOWN) {
583 goto end;
584 }
585
586 /* Make sure last byte order is compatible with the next byte order */
587 switch (btr->last_bo) {
588 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
589 case BT_CTF_BYTE_ORDER_NETWORK:
590 if (next_bo != BT_CTF_BYTE_ORDER_BIG_ENDIAN &&
591 next_bo != BT_CTF_BYTE_ORDER_NETWORK) {
592 status = BT_CTF_BTR_STATUS_ERROR;
593 }
594 break;
595 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
596 if (next_bo != BT_CTF_BYTE_ORDER_LITTLE_ENDIAN) {
597 status = BT_CTF_BTR_STATUS_ERROR;
598 }
599 break;
600 default:
601 status = BT_CTF_BTR_STATUS_ERROR;
602 }
603
604 end:
605 if (status) {
606 BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
607 "btr-addr=%p, last-bo=%s, next-bo=%s",
608 btr, bt_ctf_byte_order_string(btr->last_bo),
609 bt_ctf_byte_order_string(next_bo));
610 }
611
612 return status;
613 }
614
615 static
616 enum bt_ctf_btr_status read_basic_float_and_call_cb(struct bt_ctf_btr *btr,
617 const uint8_t *buf, size_t at)
618 {
619 int ret;
620 double dblval;
621 int64_t field_size;
622 enum bt_ctf_byte_order bo;
623 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
624
625 field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
626 bo = bt_ctf_field_type_get_byte_order(btr->cur_basic_field_type);
627 btr->cur_bo = bo;
628
629 switch (field_size) {
630 case 32:
631 {
632 uint64_t v;
633 union {
634 uint32_t u;
635 float f;
636 } f32;
637
638 ret = bt_ctf_field_type_floating_point_get_mantissa_digits(
639 btr->cur_basic_field_type);
640 assert(ret == 24);
641 ret = bt_ctf_field_type_floating_point_get_exponent_digits(
642 btr->cur_basic_field_type);
643 assert(ret == 8);
644 status = read_unsigned_bitfield(buf, at, field_size, bo, &v);
645 if (status != BT_CTF_BTR_STATUS_OK) {
646 BT_LOGW("Cannot read unsigned 32-bit bit array for floating point number field: "
647 "btr-addr=%p, status=%s",
648 btr, bt_ctf_btr_status_string(status));
649 goto end;
650 }
651
652 f32.u = (uint32_t) v;
653 dblval = (double) f32.f;
654 break;
655 }
656 case 64:
657 {
658 union {
659 uint64_t u;
660 double d;
661 } f64;
662
663 ret = bt_ctf_field_type_floating_point_get_mantissa_digits(
664 btr->cur_basic_field_type);
665 assert(ret == 53);
666 ret = bt_ctf_field_type_floating_point_get_exponent_digits(
667 btr->cur_basic_field_type);
668 assert(ret == 11);
669 status = read_unsigned_bitfield(buf, at, field_size, bo,
670 &f64.u);
671 if (status != BT_CTF_BTR_STATUS_OK) {
672 BT_LOGW("Cannot read unsigned 64-bit bit array for floating point number field: "
673 "btr-addr=%p, status=%s",
674 btr, bt_ctf_btr_status_string(status));
675 goto end;
676 }
677
678 dblval = f64.d;
679 break;
680 }
681 default:
682 /* Only 32-bit and 64-bit fields are supported currently */
683 BT_LOGW("Only 32-bit and 64-bit floating point number fields are supported: "
684 "btr-addr=%p", btr);
685 status = BT_CTF_BTR_STATUS_ERROR;
686 goto end;
687 }
688
689 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
690 btr, at, dblval);
691
692 if (btr->user.cbs.types.floating_point) {
693 BT_LOGV("Calling user function (floating point number).");
694 status = btr->user.cbs.types.floating_point(dblval,
695 btr->cur_basic_field_type, btr->user.data);
696 BT_LOGV("User function returned: status=%s",
697 bt_ctf_btr_status_string(status));
698 if (status != BT_CTF_BTR_STATUS_OK) {
699 BT_LOGW("User function failed: btr-addr=%p, status=%s",
700 btr, bt_ctf_btr_status_string(status));
701 }
702 }
703
704 end:
705 return status;
706 }
707
708 static inline
709 enum bt_ctf_btr_status read_basic_int_and_call(struct bt_ctf_btr *btr,
710 const uint8_t *buf, size_t at,
711 struct bt_ctf_field_type *int_type,
712 struct bt_ctf_field_type *orig_type)
713 {
714 int signd;
715 int64_t field_size;
716 enum bt_ctf_byte_order bo;
717 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
718
719 signd = bt_ctf_field_type_integer_get_signed(int_type);
720 field_size = get_basic_field_type_size(btr, int_type);
721 if (field_size < 1) {
722 BT_LOGW("Cannot get integer field type's size: "
723 "btr=%p, at=%zu, ft-addr=%p",
724 btr, at, int_type);
725 status = BT_CTF_BTR_STATUS_ERROR;
726 goto end;
727 }
728
729 bo = bt_ctf_field_type_get_byte_order(int_type);
730
731 /*
732 * Update current byte order now because we could be reading
733 * the integer value of an enumeration type, and thus we know
734 * here the actual supporting integer type's byte order.
735 */
736 btr->cur_bo = bo;
737
738 if (signd) {
739 int64_t v;
740
741 status = read_signed_bitfield(buf, at, field_size, bo, &v);
742 if (status != BT_CTF_BTR_STATUS_OK) {
743 BT_LOGW("Cannot read signed bit array for signed integer field: "
744 "btr-addr=%p, status=%s",
745 btr, bt_ctf_btr_status_string(status));
746 goto end;
747 }
748
749 if (btr->user.cbs.types.signed_int) {
750 BT_LOGV("Calling user function (signed integer).");
751 status = btr->user.cbs.types.signed_int(v,
752 btr->cur_basic_field_type, btr->user.data);
753 BT_LOGV("User function returned: status=%s",
754 bt_ctf_btr_status_string(status));
755 if (status != BT_CTF_BTR_STATUS_OK) {
756 BT_LOGW("User function failed: "
757 "btr-addr=%p, status=%s",
758 btr, bt_ctf_btr_status_string(status));
759 }
760 }
761 } else {
762 uint64_t v;
763
764 status = read_unsigned_bitfield(buf, at, field_size, bo, &v);
765 if (status != BT_CTF_BTR_STATUS_OK) {
766 BT_LOGW("Cannot read unsigned bit array for unsigned integer field: "
767 "btr-addr=%p, status=%s",
768 btr, bt_ctf_btr_status_string(status));
769 goto end;
770 }
771
772 if (btr->user.cbs.types.unsigned_int) {
773 BT_LOGV("Calling user function (unsigned integer).");
774 status = btr->user.cbs.types.unsigned_int(v,
775 btr->cur_basic_field_type, btr->user.data);
776 BT_LOGV("User function returned: status=%s",
777 bt_ctf_btr_status_string(status));
778 if (status != BT_CTF_BTR_STATUS_OK) {
779 BT_LOGW("User function failed: "
780 "btr-addr=%p, status=%s",
781 btr, bt_ctf_btr_status_string(status));
782 }
783 }
784 }
785
786 end:
787 return status;
788 }
789
790 static
791 enum bt_ctf_btr_status read_basic_int_and_call_cb(struct bt_ctf_btr *btr,
792 const uint8_t *buf, size_t at)
793 {
794 return read_basic_int_and_call(btr, buf, at, btr->cur_basic_field_type,
795 btr->cur_basic_field_type);
796 }
797
798 static
799 enum bt_ctf_btr_status read_basic_enum_and_call_cb(struct bt_ctf_btr *btr,
800 const uint8_t *buf, size_t at)
801 {
802 struct bt_ctf_field_type *int_field_type;
803 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
804
805 int_field_type = bt_ctf_field_type_enumeration_get_container_type(
806 btr->cur_basic_field_type);
807 assert(int_field_type);
808 status = read_basic_int_and_call(btr, buf, at,
809 int_field_type, btr->cur_basic_field_type);
810 bt_put(int_field_type);
811 return status;
812 }
813
814 static inline
815 enum bt_ctf_btr_status read_basic_type_and_call_continue(struct bt_ctf_btr *btr,
816 read_basic_and_call_cb_t read_basic_and_call_cb)
817 {
818 size_t available;
819 int64_t field_size;
820 int64_t needed_bits;
821 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
822
823 if (!at_least_one_bit_left(btr)) {
824 BT_LOGV("Reached end of data: btr-addr=%p", btr);
825 status = BT_CTF_BTR_STATUS_EOF;
826 goto end;
827 }
828
829 field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
830 if (field_size < 1) {
831 BT_LOGW("Cannot get basic field type's size: "
832 "btr-addr=%p, ft-addr=%p",
833 btr, btr->cur_basic_field_type);
834 status = BT_CTF_BTR_STATUS_ERROR;
835 goto end;
836 }
837
838 available = available_bits(btr);
839 needed_bits = field_size - btr->stitch.at;
840 BT_LOGV("Continuing basic field decoding: "
841 "btr-addr=%p, field-size=%" PRId64 ", needed-size=%" PRId64 ", "
842 "available-size=%zu",
843 btr, field_size, needed_bits, available);
844 if (needed_bits <= available) {
845 /* We have all the bits; append to stitch, then decode */
846 stitch_append_from_buf(btr, needed_bits);
847 status = read_basic_and_call_cb(btr, btr->stitch.buf,
848 btr->stitch.offset);
849 if (status != BT_CTF_BTR_STATUS_OK) {
850 BT_LOGW("Cannot read basic field: "
851 "btr-addr=%p, ft-addr=%p, status=%s",
852 btr, btr->cur_basic_field_type,
853 bt_ctf_btr_status_string(status));
854 goto end;
855 }
856
857 if (stack_empty(btr->stack)) {
858 /* Root is a basic type */
859 btr->state = BTR_STATE_DONE;
860 } else {
861 /* Go to next field */
862 stack_top(btr->stack)->index++;
863 btr->state = BTR_STATE_NEXT_FIELD;
864 btr->last_bo = btr->cur_bo;
865 }
866 goto end;
867 }
868
869 /* We are here; it means we don't have enough data to decode this */
870 BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer.");
871 stitch_append_from_remaining_buf(btr);
872 status = BT_CTF_BTR_STATUS_EOF;
873
874 end:
875 return status;
876 }
877
878 static inline
879 enum bt_ctf_btr_status read_basic_type_and_call_begin(struct bt_ctf_btr *btr,
880 read_basic_and_call_cb_t read_basic_and_call_cb)
881 {
882 size_t available;
883 int64_t field_size;
884 enum bt_ctf_byte_order bo;
885 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
886
887 if (!at_least_one_bit_left(btr)) {
888 BT_LOGV("Reached end of data: btr-addr=%p", btr);
889 status = BT_CTF_BTR_STATUS_EOF;
890 goto end;
891 }
892
893 field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
894 if (field_size < 1) {
895 BT_LOGW("Cannot get basic field type's size: "
896 "btr-addr=%p, ft-addr=%p",
897 btr, btr->cur_basic_field_type);
898 status = BT_CTF_BTR_STATUS_ERROR;
899 goto end;
900 }
901
902 bo = bt_ctf_field_type_get_byte_order(btr->cur_basic_field_type);
903 status = validate_contiguous_bo(btr, bo);
904 if (status != BT_CTF_BTR_STATUS_OK) {
905 /* validate_contiguous_bo() logs errors */
906 goto end;
907 }
908
909 available = available_bits(btr);
910
911 if (field_size <= available) {
912 /* We have all the bits; decode and set now */
913 status = read_basic_and_call_cb(btr, btr->buf.addr,
914 buf_at_from_addr(btr));
915 if (status != BT_CTF_BTR_STATUS_OK) {
916 BT_LOGW("Cannot read basic field: "
917 "btr-addr=%p, ft-addr=%p, status=%s",
918 btr, btr->cur_basic_field_type,
919 bt_ctf_btr_status_string(status));
920 goto end;
921 }
922
923 consume_bits(btr, field_size);
924
925 if (stack_empty(btr->stack)) {
926 /* Root is a basic type */
927 btr->state = BTR_STATE_DONE;
928 } else {
929 /* Go to next field */
930 stack_top(btr->stack)->index++;
931 btr->state = BTR_STATE_NEXT_FIELD;
932 btr->last_bo = btr->cur_bo;
933 }
934
935 goto end;
936 }
937
938 /* We are here; it means we don't have enough data to decode this */
939 BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer.");
940 stitch_set_from_remaining_buf(btr);
941 btr->state = BTR_STATE_READ_BASIC_CONTINUE;
942 status = BT_CTF_BTR_STATUS_EOF;
943
944 end:
945 return status;
946 }
947
948 static inline
949 enum bt_ctf_btr_status read_basic_int_type_and_call_begin(
950 struct bt_ctf_btr *btr)
951 {
952 return read_basic_type_and_call_begin(btr, read_basic_int_and_call_cb);
953 }
954
955 static inline
956 enum bt_ctf_btr_status read_basic_int_type_and_call_continue(
957 struct bt_ctf_btr *btr)
958 {
959 return read_basic_type_and_call_continue(btr,
960 read_basic_int_and_call_cb);
961 }
962
963 static inline
964 enum bt_ctf_btr_status read_basic_float_type_and_call_begin(
965 struct bt_ctf_btr *btr)
966 {
967 return read_basic_type_and_call_begin(btr,
968 read_basic_float_and_call_cb);
969 }
970
971 static inline
972 enum bt_ctf_btr_status read_basic_float_type_and_call_continue(
973 struct bt_ctf_btr *btr)
974 {
975 return read_basic_type_and_call_continue(btr,
976 read_basic_float_and_call_cb);
977 }
978
979 static inline
980 enum bt_ctf_btr_status read_basic_enum_type_and_call_begin(
981 struct bt_ctf_btr *btr)
982 {
983 return read_basic_type_and_call_begin(btr,
984 read_basic_enum_and_call_cb);
985 }
986
987 static inline
988 enum bt_ctf_btr_status read_basic_enum_type_and_call_continue(
989 struct bt_ctf_btr *btr)
990 {
991 return read_basic_type_and_call_continue(btr,
992 read_basic_enum_and_call_cb);
993 }
994
995 static inline
996 enum bt_ctf_btr_status read_basic_string_type_and_call(
997 struct bt_ctf_btr *btr, bool begin)
998 {
999 size_t buf_at_bytes;
1000 const uint8_t *result;
1001 size_t available_bytes;
1002 const uint8_t *first_chr;
1003 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1004
1005 if (!at_least_one_bit_left(btr)) {
1006 BT_LOGV("Reached end of data: btr-addr=%p", btr);
1007 status = BT_CTF_BTR_STATUS_EOF;
1008 goto end;
1009 }
1010
1011 assert(buf_at_from_addr(btr) % 8 == 0);
1012 available_bytes = BITS_TO_BYTES_FLOOR(available_bits(btr));
1013 buf_at_bytes = BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr));
1014 first_chr = &btr->buf.addr[buf_at_bytes];
1015 result = memchr(first_chr, '\0', available_bytes);
1016
1017 if (begin && btr->user.cbs.types.string_begin) {
1018 BT_LOGV("Calling user function (string, beginning).");
1019 status = btr->user.cbs.types.string_begin(
1020 btr->cur_basic_field_type, btr->user.data);
1021 BT_LOGV("User function returned: status=%s",
1022 bt_ctf_btr_status_string(status));
1023 if (status != BT_CTF_BTR_STATUS_OK) {
1024 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1025 btr, bt_ctf_btr_status_string(status));
1026 goto end;
1027 }
1028 }
1029
1030 if (!result) {
1031 /* No null character yet */
1032 if (btr->user.cbs.types.string) {
1033 BT_LOGV("Calling user function (substring).");
1034 status = btr->user.cbs.types.string(
1035 (const char *) first_chr,
1036 available_bytes, btr->cur_basic_field_type,
1037 btr->user.data);
1038 BT_LOGV("User function returned: status=%s",
1039 bt_ctf_btr_status_string(status));
1040 if (status != BT_CTF_BTR_STATUS_OK) {
1041 BT_LOGW("User function failed: "
1042 "btr-addr=%p, status=%s",
1043 btr, bt_ctf_btr_status_string(status));
1044 goto end;
1045 }
1046 }
1047
1048 consume_bits(btr, BYTES_TO_BITS(available_bytes));
1049 btr->state = BTR_STATE_READ_BASIC_CONTINUE;
1050 status = BT_CTF_BTR_STATUS_EOF;
1051 } else {
1052 /* Found the null character */
1053 size_t result_len = (size_t) (result - first_chr);
1054
1055 if (btr->user.cbs.types.string && result_len) {
1056 BT_LOGV("Calling user function (substring).");
1057 status = btr->user.cbs.types.string(
1058 (const char *) first_chr,
1059 result_len, btr->cur_basic_field_type,
1060 btr->user.data);
1061 BT_LOGV("User function returned: status=%s",
1062 bt_ctf_btr_status_string(status));
1063 if (status != BT_CTF_BTR_STATUS_OK) {
1064 BT_LOGW("User function failed: "
1065 "btr-addr=%p, status=%s",
1066 btr, bt_ctf_btr_status_string(status));
1067 goto end;
1068 }
1069 }
1070
1071 if (btr->user.cbs.types.string_end) {
1072 BT_LOGV("Calling user function (string, end).");
1073 status = btr->user.cbs.types.string_end(
1074 btr->cur_basic_field_type, btr->user.data);
1075 BT_LOGV("User function returned: status=%s",
1076 bt_ctf_btr_status_string(status));
1077 if (status != BT_CTF_BTR_STATUS_OK) {
1078 BT_LOGW("User function failed: "
1079 "btr-addr=%p, status=%s",
1080 btr, bt_ctf_btr_status_string(status));
1081 goto end;
1082 }
1083 }
1084
1085 consume_bits(btr, BYTES_TO_BITS(result_len + 1));
1086
1087 if (stack_empty(btr->stack)) {
1088 /* Root is a basic type */
1089 btr->state = BTR_STATE_DONE;
1090 } else {
1091 /* Go to next field */
1092 stack_top(btr->stack)->index++;
1093 btr->state = BTR_STATE_NEXT_FIELD;
1094 btr->last_bo = btr->cur_bo;
1095 }
1096 }
1097
1098 end:
1099 return status;
1100 }
1101
1102 static inline
1103 enum bt_ctf_btr_status read_basic_begin_state(struct bt_ctf_btr *btr)
1104 {
1105 enum bt_ctf_btr_status status;
1106
1107 assert(btr->cur_basic_field_type);
1108
1109 switch (bt_ctf_field_type_get_type_id(btr->cur_basic_field_type)) {
1110 case BT_CTF_FIELD_TYPE_ID_INTEGER:
1111 status = read_basic_int_type_and_call_begin(btr);
1112 break;
1113 case BT_CTF_FIELD_TYPE_ID_FLOAT:
1114 status = read_basic_float_type_and_call_begin(btr);
1115 break;
1116 case BT_CTF_FIELD_TYPE_ID_ENUM:
1117 status = read_basic_enum_type_and_call_begin(btr);
1118 break;
1119 case BT_CTF_FIELD_TYPE_ID_STRING:
1120 status = read_basic_string_type_and_call(btr, true);
1121 break;
1122 default:
1123 BT_LOGF("Unknown basic field type ID: "
1124 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1125 btr, btr->cur_basic_field_type,
1126 bt_ctf_field_type_id_string(
1127 bt_ctf_field_type_get_type_id(
1128 btr->cur_basic_field_type)));
1129 abort();
1130 }
1131
1132 return status;
1133 }
1134
1135 static inline
1136 enum bt_ctf_btr_status read_basic_continue_state(struct bt_ctf_btr *btr)
1137 {
1138 enum bt_ctf_btr_status status;
1139
1140 assert(btr->cur_basic_field_type);
1141
1142 switch (bt_ctf_field_type_get_type_id(btr->cur_basic_field_type)) {
1143 case BT_CTF_FIELD_TYPE_ID_INTEGER:
1144 status = read_basic_int_type_and_call_continue(btr);
1145 break;
1146 case BT_CTF_FIELD_TYPE_ID_FLOAT:
1147 status = read_basic_float_type_and_call_continue(btr);
1148 break;
1149 case BT_CTF_FIELD_TYPE_ID_ENUM:
1150 status = read_basic_enum_type_and_call_continue(btr);
1151 break;
1152 case BT_CTF_FIELD_TYPE_ID_STRING:
1153 status = read_basic_string_type_and_call(btr, false);
1154 break;
1155 default:
1156 BT_LOGF("Unknown basic field type ID: "
1157 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1158 btr, btr->cur_basic_field_type,
1159 bt_ctf_field_type_id_string(
1160 bt_ctf_field_type_get_type_id(
1161 btr->cur_basic_field_type)));
1162 abort();
1163 }
1164
1165 return status;
1166 }
1167
1168 static inline
1169 size_t bits_to_skip_to_align_to(struct bt_ctf_btr *btr, size_t align)
1170 {
1171 size_t aligned_packet_at;
1172
1173 aligned_packet_at = ALIGN(packet_at(btr), align);
1174 return aligned_packet_at - packet_at(btr);
1175 }
1176
1177 static inline
1178 enum bt_ctf_btr_status align_type_state(struct bt_ctf_btr *btr,
1179 struct bt_ctf_field_type *field_type, enum btr_state next_state)
1180 {
1181 int field_alignment;
1182 size_t skip_bits;
1183 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1184
1185 /* Get field's alignment */
1186 field_alignment = bt_ctf_field_type_get_alignment(field_type);
1187 if (field_alignment < 0) {
1188 BT_LOGW("Cannot get field type's alignment: "
1189 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1190 btr, field_type,
1191 bt_ctf_field_type_id_string(
1192 bt_ctf_field_type_get_type_id(field_type)));
1193 status = BT_CTF_BTR_STATUS_ERROR;
1194 goto end;
1195 }
1196
1197 /*
1198 * 0 means "undefined" for variants; what we really want is 1
1199 * (always aligned)
1200 */
1201 if (field_alignment == 0) {
1202 field_alignment = 1;
1203 }
1204
1205 /* Compute how many bits we need to skip */
1206 skip_bits = bits_to_skip_to_align_to(btr, field_alignment);
1207
1208 /* Nothing to skip? aligned */
1209 if (skip_bits == 0) {
1210 btr->state = next_state;
1211 goto end;
1212 }
1213
1214 /* Make sure there's at least one bit left */
1215 if (!at_least_one_bit_left(btr)) {
1216 status = BT_CTF_BTR_STATUS_EOF;
1217 goto end;
1218 }
1219
1220 /* Consume as many bits as possible in what's left */
1221 consume_bits(btr, MIN(available_bits(btr), skip_bits));
1222
1223 /* Are we done now? */
1224 skip_bits = bits_to_skip_to_align_to(btr, field_alignment);
1225 if (skip_bits == 0) {
1226 /* Yes: go to next state */
1227 btr->state = next_state;
1228 goto end;
1229 } else {
1230 /* No: need more data */
1231 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr);
1232 status = BT_CTF_BTR_STATUS_EOF;
1233 }
1234
1235 end:
1236 return status;
1237 }
1238
1239 static inline
1240 bool is_compound_type(struct bt_ctf_field_type *field_type)
1241 {
1242 enum bt_ctf_field_type_id id = bt_ctf_field_type_get_type_id(field_type);
1243
1244 return id == BT_CTF_FIELD_TYPE_ID_STRUCT || id == BT_CTF_FIELD_TYPE_ID_ARRAY ||
1245 id == BT_CTF_FIELD_TYPE_ID_SEQUENCE || id == BT_CTF_FIELD_TYPE_ID_VARIANT;
1246 }
1247
1248 static inline
1249 enum bt_ctf_btr_status next_field_state(struct bt_ctf_btr *btr)
1250 {
1251 int ret;
1252 struct stack_entry *top;
1253 struct bt_ctf_field_type *next_field_type = NULL;
1254 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1255
1256 if (stack_empty(btr->stack)) {
1257 goto end;
1258 }
1259
1260 top = stack_top(btr->stack);
1261
1262 /* Are we done with this base type? */
1263 while (top->index == top->base_len) {
1264 if (btr->user.cbs.types.compound_end) {
1265 BT_LOGV("Calling user function (compound, end).");
1266 status = btr->user.cbs.types.compound_end(
1267 top->base_type, btr->user.data);
1268 BT_LOGV("User function returned: status=%s",
1269 bt_ctf_btr_status_string(status));
1270 if (status != BT_CTF_BTR_STATUS_OK) {
1271 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1272 btr, bt_ctf_btr_status_string(status));
1273 goto end;
1274 }
1275 }
1276
1277 stack_pop(btr->stack);
1278
1279 /* Are we done with the root type? */
1280 if (stack_empty(btr->stack)) {
1281 btr->state = BTR_STATE_DONE;
1282 goto end;
1283 }
1284
1285 top = stack_top(btr->stack);
1286 top->index++;
1287 }
1288
1289 /* Get next field's type */
1290 switch (bt_ctf_field_type_get_type_id(top->base_type)) {
1291 case BT_CTF_FIELD_TYPE_ID_STRUCT:
1292 ret = bt_ctf_field_type_structure_get_field(
1293 top->base_type, NULL, &next_field_type,
1294 top->index);
1295 if (ret) {
1296 next_field_type = NULL;
1297 }
1298 break;
1299 case BT_CTF_FIELD_TYPE_ID_ARRAY:
1300 next_field_type =
1301 bt_ctf_field_type_array_get_element_type(
1302 top->base_type);
1303 break;
1304 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
1305 next_field_type =
1306 bt_ctf_field_type_sequence_get_element_type(
1307 top->base_type);
1308 break;
1309 case BT_CTF_FIELD_TYPE_ID_VARIANT:
1310 /* Variant types are dynamic: query the user, he should know! */
1311 next_field_type =
1312 btr->user.cbs.query.get_variant_type(
1313 top->base_type, btr->user.data);
1314 break;
1315 default:
1316 break;
1317 }
1318
1319 if (!next_field_type) {
1320 BT_LOGW("Cannot get the field type of the next field: "
1321 "btr-addr=%p, base-ft-addr=%p, base-ft-id=%s, "
1322 "index=%" PRId64,
1323 btr, top->base_type,
1324 bt_ctf_field_type_id_string(
1325 bt_ctf_field_type_get_type_id(top->base_type)),
1326 top->index);
1327 status = BT_CTF_BTR_STATUS_ERROR;
1328 goto end;
1329 }
1330
1331 if (is_compound_type(next_field_type)) {
1332 if (btr->user.cbs.types.compound_begin) {
1333 BT_LOGV("Calling user function (compound, begin).");
1334 status = btr->user.cbs.types.compound_begin(
1335 next_field_type, btr->user.data);
1336 BT_LOGV("User function returned: status=%s",
1337 bt_ctf_btr_status_string(status));
1338 if (status != BT_CTF_BTR_STATUS_OK) {
1339 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1340 btr, bt_ctf_btr_status_string(status));
1341 goto end;
1342 }
1343 }
1344
1345 ret = stack_push_with_len(btr, next_field_type);
1346 if (ret) {
1347 /* stack_push_with_len() logs errors */
1348 status = BT_CTF_BTR_STATUS_ERROR;
1349 goto end;
1350 }
1351
1352 /* Next state: align a compound type */
1353 btr->state = BTR_STATE_ALIGN_COMPOUND;
1354 } else {
1355 /* Replace current basic field type */
1356 BT_LOGV("Replacing current basic field type: "
1357 "btr-addr=%p, cur-basic-ft-addr=%p, "
1358 "next-basic-ft-addr=%p",
1359 btr, btr->cur_basic_field_type, next_field_type);
1360 BT_MOVE(btr->cur_basic_field_type, next_field_type);
1361
1362 /* Next state: align a basic type */
1363 btr->state = BTR_STATE_ALIGN_BASIC;
1364 }
1365
1366 end:
1367 BT_PUT(next_field_type);
1368
1369 return status;
1370 }
1371
1372 static inline
1373 enum bt_ctf_btr_status handle_state(struct bt_ctf_btr *btr)
1374 {
1375 enum bt_ctf_btr_status status = BT_CTF_BTR_STATUS_OK;
1376
1377 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1378 btr, btr_state_string(btr->state));
1379
1380 switch (btr->state) {
1381 case BTR_STATE_NEXT_FIELD:
1382 status = next_field_state(btr);
1383 break;
1384 case BTR_STATE_ALIGN_BASIC:
1385 status = align_type_state(btr, btr->cur_basic_field_type,
1386 BTR_STATE_READ_BASIC_BEGIN);
1387 break;
1388 case BTR_STATE_ALIGN_COMPOUND:
1389 status = align_type_state(btr, stack_top(btr->stack)->base_type,
1390 BTR_STATE_NEXT_FIELD);
1391 break;
1392 case BTR_STATE_READ_BASIC_BEGIN:
1393 status = read_basic_begin_state(btr);
1394 break;
1395 case BTR_STATE_READ_BASIC_CONTINUE:
1396 status = read_basic_continue_state(btr);
1397 break;
1398 case BTR_STATE_DONE:
1399 break;
1400 }
1401
1402 BT_LOGV("Handled state: btr-addr=%p, status=%s",
1403 btr, bt_ctf_btr_status_string(status));
1404 return status;
1405 }
1406
1407 struct bt_ctf_btr *bt_ctf_btr_create(struct bt_ctf_btr_cbs cbs, void *data,
1408 FILE *err_stream)
1409 {
1410 struct bt_ctf_btr *btr;
1411
1412 BT_LOGD_STR("Creating binary type reader (BTR).");
1413 btr = g_new0(struct bt_ctf_btr, 1);
1414 if (!btr) {
1415 BT_LOGE_STR("Failed to allocate one binary type reader.");
1416 goto end;
1417 }
1418
1419 btr->stack = stack_new();
1420 if (!btr->stack) {
1421 BT_LOGE_STR("Cannot create BTR's stack.");
1422 bt_ctf_btr_destroy(btr);
1423 btr = NULL;
1424 goto end;
1425 }
1426
1427 btr->state = BTR_STATE_NEXT_FIELD;
1428 btr->user.cbs = cbs;
1429 btr->user.data = data;
1430 btr->err_stream = err_stream;
1431 BT_LOGD("Created BTR: addr=%p", btr);
1432
1433 end:
1434 return btr;
1435 }
1436
1437 void bt_ctf_btr_destroy(struct bt_ctf_btr *btr)
1438 {
1439 if (btr->stack) {
1440 stack_destroy(btr->stack);
1441 }
1442
1443 BT_LOGD("Destroying BTR: addr=%p", btr);
1444 BT_PUT(btr->cur_basic_field_type);
1445 g_free(btr);
1446 }
1447
1448 static
1449 void reset(struct bt_ctf_btr *btr)
1450 {
1451 BT_LOGD("Resetting BTR: addr=%p", btr);
1452 stack_clear(btr->stack);
1453 BT_PUT(btr->cur_basic_field_type);
1454 stitch_reset(btr);
1455 btr->buf.addr = NULL;
1456 btr->last_bo = BT_CTF_BYTE_ORDER_UNKNOWN;
1457 }
1458
1459 static
1460 void update_packet_offset(struct bt_ctf_btr *btr)
1461 {
1462 BT_LOGV("Updating packet offset for next call: "
1463 "btr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1464 btr, btr->buf.packet_offset,
1465 btr->buf.packet_offset + btr->buf.at);
1466 btr->buf.packet_offset += btr->buf.at;
1467 }
1468
1469 size_t bt_ctf_btr_start(struct bt_ctf_btr *btr,
1470 struct bt_ctf_field_type *type, const uint8_t *buf,
1471 size_t offset, size_t packet_offset, size_t sz,
1472 enum bt_ctf_btr_status *status)
1473 {
1474 assert(btr);
1475 assert(buf);
1476 assert(sz > 0);
1477 assert(BYTES_TO_BITS(sz) > offset);
1478 reset(btr);
1479 btr->buf.addr = buf;
1480 btr->buf.offset = offset;
1481 btr->buf.at = 0;
1482 btr->buf.packet_offset = packet_offset;
1483 btr->buf.buf_sz = sz;
1484 btr->buf.sz = BYTES_TO_BITS(sz) - offset;
1485 *status = BT_CTF_BTR_STATUS_OK;
1486
1487 BT_LOGV("Starting decoding: btr-addr=%p, ft-addr=%p, "
1488 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1489 "packet-offset=%zu",
1490 btr, type, buf, sz, offset, packet_offset);
1491
1492 /* Set root type */
1493 if (is_compound_type(type)) {
1494 /* Compound type: push on visit stack */
1495 int stack_ret;
1496
1497 if (btr->user.cbs.types.compound_begin) {
1498 BT_LOGV("Calling user function (compound, begin).");
1499 *status = btr->user.cbs.types.compound_begin(
1500 type, btr->user.data);
1501 BT_LOGV("User function returned: status=%s",
1502 bt_ctf_btr_status_string(*status));
1503 if (*status != BT_CTF_BTR_STATUS_OK) {
1504 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1505 btr, bt_ctf_btr_status_string(*status));
1506 goto end;
1507 }
1508 }
1509
1510 stack_ret = stack_push_with_len(btr, type);
1511 if (stack_ret) {
1512 /* stack_push_with_len() logs errors */
1513 *status = BT_CTF_BTR_STATUS_ERROR;
1514 goto end;
1515 }
1516
1517 btr->state = BTR_STATE_ALIGN_COMPOUND;
1518 } else {
1519 /* Basic type: set as current basic type */
1520 btr->cur_basic_field_type = type;
1521 bt_get(btr->cur_basic_field_type);
1522 btr->state = BTR_STATE_ALIGN_BASIC;
1523 }
1524
1525 /* Run the machine! */
1526 BT_LOGV_STR("Running the state machine.");
1527
1528 while (true) {
1529 *status = handle_state(btr);
1530 if (*status != BT_CTF_BTR_STATUS_OK) {
1531 break;
1532 } else if (btr->state == BTR_STATE_DONE) {
1533 break;
1534 }
1535 }
1536
1537 /* Update packet offset for next time */
1538 update_packet_offset(btr);
1539
1540 end:
1541 return btr->buf.at;
1542 }
1543
1544 size_t bt_ctf_btr_continue(struct bt_ctf_btr *btr,
1545 const uint8_t *buf, size_t sz,
1546 enum bt_ctf_btr_status *status)
1547 {
1548 assert(btr);
1549 assert(buf);
1550 assert(sz > 0);
1551 btr->buf.addr = buf;
1552 btr->buf.offset = 0;
1553 btr->buf.at = 0;
1554 btr->buf.buf_sz = sz;
1555 btr->buf.sz = BYTES_TO_BITS(sz);
1556 *status = BT_CTF_BTR_STATUS_OK;
1557
1558 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1559 btr, buf, sz);
1560
1561 /* Continue running the machine */
1562 BT_LOGV_STR("Running the state machine.");
1563
1564 while (true) {
1565 *status = handle_state(btr);
1566 if (*status != BT_CTF_BTR_STATUS_OK) {
1567 break;
1568 } else if (btr->state == BTR_STATE_DONE) {
1569 break;
1570 }
1571 }
1572
1573 /* Update packet offset for next time */
1574 update_packet_offset(btr);
1575 return btr->buf.at;
1576 }
This page took 0.0652 seconds and 5 git commands to generate.