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