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