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