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