Split CTF IR and CTF writer APIs and implementations
[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 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_common_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 BT_ASSERT(stack);
268 BT_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_common_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_common_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 BT_ASSERT(stack);
319
320 return stack->entries->len;
321 }
322
323 static
324 void stack_pop(struct stack *stack)
325 {
326 BT_ASSERT(stack);
327 BT_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 BT_ASSERT(stack);
344
345 if (!stack_empty(stack)) {
346 g_ptr_array_remove_range(stack->entries, 0, stack_size(stack));
347 }
348
349 BT_ASSERT(stack_empty(stack));
350 }
351
352 static inline
353 struct stack_entry *stack_top(struct stack *stack)
354 {
355 BT_ASSERT(stack);
356 BT_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 BT_ASSERT(exp_dig >= 0);
433 BT_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_field_type(
442 field_type);
443 BT_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 BT_ASSERT(nb_bytes > 0);
485 BT_ASSERT(btr->buf.addr);
486 memcpy(&btr->stitch.buf[stitch_byte_at], &btr->buf.addr[buf_byte_at],
487 nb_bytes);
488 btr->stitch.at += sz;
489 consume_bits(btr, sz);
490 }
491
492 static
493 void stitch_append_from_remaining_buf(struct bt_btr *btr)
494 {
495 stitch_append_from_buf(btr, available_bits(btr));
496 }
497
498 static
499 void stitch_set_from_remaining_buf(struct bt_btr *btr)
500 {
501 stitch_reset(btr);
502 btr->stitch.offset = IN_BYTE_OFFSET(buf_at_from_addr(btr));
503 stitch_append_from_remaining_buf(btr);
504 }
505
506 static inline
507 enum bt_btr_status read_unsigned_bitfield(const uint8_t *buf, size_t at,
508 int64_t field_size, enum bt_byte_order bo, uint64_t *v)
509 {
510 enum bt_btr_status status = BT_BTR_STATUS_OK;
511
512 switch (bo) {
513 case BT_BYTE_ORDER_BIG_ENDIAN:
514 case BT_BYTE_ORDER_NETWORK:
515 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
516 break;
517 case BT_BYTE_ORDER_LITTLE_ENDIAN:
518 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
519 break;
520 default:
521 BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo);
522 abort();
523 }
524
525 BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64 ", "
526 "bo=%s, val=%" PRIu64, at, field_size,
527 bt_common_byte_order_string(bo), *v);
528 return status;
529 }
530
531 static inline
532 enum bt_btr_status read_signed_bitfield(const uint8_t *buf, size_t at,
533 int64_t field_size, enum bt_byte_order bo, int64_t *v)
534 {
535 enum bt_btr_status status = BT_BTR_STATUS_OK;
536
537 switch (bo) {
538 case BT_BYTE_ORDER_BIG_ENDIAN:
539 case BT_BYTE_ORDER_NETWORK:
540 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
541 break;
542 case BT_BYTE_ORDER_LITTLE_ENDIAN:
543 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
544 break;
545 default:
546 BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo);
547 abort();
548 }
549
550 BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64 ", "
551 "bo=%s, val=%" PRId64, at, field_size,
552 bt_common_byte_order_string(bo), *v);
553 return status;
554 }
555
556 typedef enum bt_btr_status (* read_basic_and_call_cb_t)(struct bt_btr *,
557 const uint8_t *, size_t);
558
559 static inline
560 enum bt_btr_status validate_contiguous_bo(struct bt_btr *btr,
561 enum bt_byte_order next_bo)
562 {
563 enum bt_btr_status status = BT_BTR_STATUS_OK;
564
565 /* Always valid when at a byte boundary */
566 if (packet_at(btr) % 8 == 0) {
567 goto end;
568 }
569
570 /* Always valid if last byte order is unknown */
571 if (btr->last_bo == BT_BYTE_ORDER_UNKNOWN) {
572 goto end;
573 }
574
575 /* Always valid if next byte order is unknown */
576 if (next_bo == BT_BYTE_ORDER_UNKNOWN) {
577 goto end;
578 }
579
580 /* Make sure last byte order is compatible with the next byte order */
581 switch (btr->last_bo) {
582 case BT_BYTE_ORDER_BIG_ENDIAN:
583 case BT_BYTE_ORDER_NETWORK:
584 if (next_bo != BT_BYTE_ORDER_BIG_ENDIAN &&
585 next_bo != BT_BYTE_ORDER_NETWORK) {
586 status = BT_BTR_STATUS_ERROR;
587 }
588 break;
589 case BT_BYTE_ORDER_LITTLE_ENDIAN:
590 if (next_bo != BT_BYTE_ORDER_LITTLE_ENDIAN) {
591 status = BT_BTR_STATUS_ERROR;
592 }
593 break;
594 default:
595 status = BT_BTR_STATUS_ERROR;
596 }
597
598 end:
599 if (status < 0) {
600 BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
601 "btr-addr=%p, last-bo=%s, next-bo=%s",
602 btr, bt_common_byte_order_string(btr->last_bo),
603 bt_common_byte_order_string(next_bo));
604 }
605
606 return status;
607 }
608
609 static
610 enum bt_btr_status read_basic_float_and_call_cb(struct bt_btr *btr,
611 const uint8_t *buf, size_t at)
612 {
613 int ret;
614 double dblval;
615 int64_t field_size;
616 enum bt_byte_order bo;
617 enum bt_btr_status status = BT_BTR_STATUS_OK;
618
619 field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
620 bo = bt_field_type_get_byte_order(btr->cur_basic_field_type);
621 btr->cur_bo = bo;
622
623 switch (field_size) {
624 case 32:
625 {
626 uint64_t v;
627 union {
628 uint32_t u;
629 float f;
630 } f32;
631
632 ret = bt_field_type_floating_point_get_mantissa_digits(
633 btr->cur_basic_field_type);
634 BT_ASSERT(ret == 24);
635 ret = bt_field_type_floating_point_get_exponent_digits(
636 btr->cur_basic_field_type);
637 BT_ASSERT(ret == 8);
638 status = read_unsigned_bitfield(buf, at, field_size, bo, &v);
639 if (status != BT_BTR_STATUS_OK) {
640 BT_LOGW("Cannot read unsigned 32-bit bit array for floating point number field: "
641 "btr-addr=%p, status=%s",
642 btr, bt_btr_status_string(status));
643 goto end;
644 }
645
646 f32.u = (uint32_t) v;
647 dblval = (double) f32.f;
648 break;
649 }
650 case 64:
651 {
652 union {
653 uint64_t u;
654 double d;
655 } f64;
656
657 ret = bt_field_type_floating_point_get_mantissa_digits(
658 btr->cur_basic_field_type);
659 BT_ASSERT(ret == 53);
660 ret = bt_field_type_floating_point_get_exponent_digits(
661 btr->cur_basic_field_type);
662 BT_ASSERT(ret == 11);
663 status = read_unsigned_bitfield(buf, at, field_size, bo,
664 &f64.u);
665 if (status != BT_BTR_STATUS_OK) {
666 BT_LOGW("Cannot read unsigned 64-bit bit array for floating point number field: "
667 "btr-addr=%p, status=%s",
668 btr, bt_btr_status_string(status));
669 goto end;
670 }
671
672 dblval = f64.d;
673 break;
674 }
675 default:
676 /* Only 32-bit and 64-bit fields are supported currently */
677 BT_LOGW("Only 32-bit and 64-bit floating point number fields are supported: "
678 "btr-addr=%p", btr);
679 status = BT_BTR_STATUS_ERROR;
680 goto end;
681 }
682
683 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
684 btr, at, dblval);
685
686 if (btr->user.cbs.types.floating_point) {
687 BT_LOGV("Calling user function (floating point number).");
688 status = btr->user.cbs.types.floating_point(dblval,
689 btr->cur_basic_field_type, btr->user.data);
690 BT_LOGV("User function returned: status=%s",
691 bt_btr_status_string(status));
692 if (status != BT_BTR_STATUS_OK) {
693 BT_LOGW("User function failed: btr-addr=%p, status=%s",
694 btr, bt_btr_status_string(status));
695 }
696 }
697
698 end:
699 return status;
700 }
701
702 static inline
703 enum bt_btr_status read_basic_int_and_call(struct bt_btr *btr,
704 const uint8_t *buf, size_t at,
705 struct bt_field_type *int_type,
706 struct bt_field_type *orig_type)
707 {
708 bt_bool signd;
709 int64_t field_size;
710 enum bt_byte_order bo;
711 enum bt_btr_status status = BT_BTR_STATUS_OK;
712
713 signd = bt_field_type_integer_is_signed(int_type);
714 field_size = get_basic_field_type_size(btr, int_type);
715 if (field_size < 1) {
716 BT_LOGW("Cannot get integer field type's size: "
717 "btr=%p, at=%zu, ft-addr=%p",
718 btr, at, int_type);
719 status = BT_BTR_STATUS_ERROR;
720 goto end;
721 }
722
723 bo = bt_field_type_get_byte_order(int_type);
724
725 /*
726 * Update current byte order now because we could be reading
727 * the integer value of an enumeration type, and thus we know
728 * here the actual supporting integer type's byte order.
729 */
730 btr->cur_bo = bo;
731
732 if (signd) {
733 int64_t v;
734
735 status = read_signed_bitfield(buf, at, field_size, bo, &v);
736 if (status != BT_BTR_STATUS_OK) {
737 BT_LOGW("Cannot read signed bit array for signed integer field: "
738 "btr-addr=%p, status=%s",
739 btr, bt_btr_status_string(status));
740 goto end;
741 }
742
743 if (btr->user.cbs.types.signed_int) {
744 BT_LOGV("Calling user function (signed integer).");
745 status = btr->user.cbs.types.signed_int(v,
746 btr->cur_basic_field_type, btr->user.data);
747 BT_LOGV("User function returned: status=%s",
748 bt_btr_status_string(status));
749 if (status != BT_BTR_STATUS_OK) {
750 BT_LOGW("User function failed: "
751 "btr-addr=%p, status=%s",
752 btr, bt_btr_status_string(status));
753 }
754 }
755 } else {
756 uint64_t v;
757
758 status = read_unsigned_bitfield(buf, at, field_size, bo, &v);
759 if (status != BT_BTR_STATUS_OK) {
760 BT_LOGW("Cannot read unsigned bit array for unsigned integer field: "
761 "btr-addr=%p, status=%s",
762 btr, bt_btr_status_string(status));
763 goto end;
764 }
765
766 if (btr->user.cbs.types.unsigned_int) {
767 BT_LOGV("Calling user function (unsigned integer).");
768 status = btr->user.cbs.types.unsigned_int(v,
769 btr->cur_basic_field_type, btr->user.data);
770 BT_LOGV("User function returned: status=%s",
771 bt_btr_status_string(status));
772 if (status != BT_BTR_STATUS_OK) {
773 BT_LOGW("User function failed: "
774 "btr-addr=%p, status=%s",
775 btr, bt_btr_status_string(status));
776 }
777 }
778 }
779
780 end:
781 return status;
782 }
783
784 static
785 enum bt_btr_status read_basic_int_and_call_cb(struct bt_btr *btr,
786 const uint8_t *buf, size_t at)
787 {
788 return read_basic_int_and_call(btr, buf, at, btr->cur_basic_field_type,
789 btr->cur_basic_field_type);
790 }
791
792 static
793 enum bt_btr_status read_basic_enum_and_call_cb(struct bt_btr *btr,
794 const uint8_t *buf, size_t at)
795 {
796 struct bt_field_type *int_field_type;
797 enum bt_btr_status status = BT_BTR_STATUS_OK;
798
799 int_field_type = bt_field_type_enumeration_get_container_field_type(
800 btr->cur_basic_field_type);
801 BT_ASSERT(int_field_type);
802 status = read_basic_int_and_call(btr, buf, at,
803 int_field_type, btr->cur_basic_field_type);
804 bt_put(int_field_type);
805 return status;
806 }
807
808 static inline
809 enum bt_btr_status read_basic_type_and_call_continue(struct bt_btr *btr,
810 read_basic_and_call_cb_t read_basic_and_call_cb)
811 {
812 size_t available;
813 int64_t field_size;
814 int64_t needed_bits;
815 enum bt_btr_status status = BT_BTR_STATUS_OK;
816
817 if (!at_least_one_bit_left(btr)) {
818 BT_LOGV("Reached end of data: btr-addr=%p", btr);
819 status = BT_BTR_STATUS_EOF;
820 goto end;
821 }
822
823 field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
824 if (field_size < 1) {
825 BT_LOGW("Cannot get basic field type's size: "
826 "btr-addr=%p, ft-addr=%p",
827 btr, btr->cur_basic_field_type);
828 status = BT_BTR_STATUS_ERROR;
829 goto end;
830 }
831
832 available = available_bits(btr);
833 needed_bits = field_size - btr->stitch.at;
834 BT_LOGV("Continuing basic field decoding: "
835 "btr-addr=%p, field-size=%" PRId64 ", needed-size=%" PRId64 ", "
836 "available-size=%zu",
837 btr, field_size, needed_bits, available);
838 if (needed_bits <= available) {
839 /* We have all the bits; append to stitch, then decode */
840 stitch_append_from_buf(btr, needed_bits);
841 status = read_basic_and_call_cb(btr, btr->stitch.buf,
842 btr->stitch.offset);
843 if (status != BT_BTR_STATUS_OK) {
844 BT_LOGW("Cannot read basic field: "
845 "btr-addr=%p, ft-addr=%p, status=%s",
846 btr, btr->cur_basic_field_type,
847 bt_btr_status_string(status));
848 goto end;
849 }
850
851 if (stack_empty(btr->stack)) {
852 /* Root is a basic type */
853 btr->state = BTR_STATE_DONE;
854 } else {
855 /* Go to next field */
856 stack_top(btr->stack)->index++;
857 btr->state = BTR_STATE_NEXT_FIELD;
858 btr->last_bo = btr->cur_bo;
859 }
860 goto end;
861 }
862
863 /* We are here; it means we don't have enough data to decode this */
864 BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer.");
865 stitch_append_from_remaining_buf(btr);
866 status = BT_BTR_STATUS_EOF;
867
868 end:
869 return status;
870 }
871
872 static inline
873 enum bt_btr_status read_basic_type_and_call_begin(struct bt_btr *btr,
874 read_basic_and_call_cb_t read_basic_and_call_cb)
875 {
876 size_t available;
877 int64_t field_size;
878 enum bt_byte_order bo;
879 enum bt_btr_status status = BT_BTR_STATUS_OK;
880
881 if (!at_least_one_bit_left(btr)) {
882 BT_LOGV("Reached end of data: btr-addr=%p", btr);
883 status = BT_BTR_STATUS_EOF;
884 goto end;
885 }
886
887 field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
888 if (field_size < 1) {
889 BT_LOGW("Cannot get basic field type's size: "
890 "btr-addr=%p, ft-addr=%p",
891 btr, btr->cur_basic_field_type);
892 status = BT_BTR_STATUS_ERROR;
893 goto end;
894 }
895
896 bo = bt_field_type_get_byte_order(btr->cur_basic_field_type);
897 status = validate_contiguous_bo(btr, bo);
898 if (status != BT_BTR_STATUS_OK) {
899 /* validate_contiguous_bo() logs errors */
900 goto end;
901 }
902
903 available = available_bits(btr);
904
905 if (field_size <= available) {
906 /* We have all the bits; decode and set now */
907 BT_ASSERT(btr->buf.addr);
908 status = read_basic_and_call_cb(btr, btr->buf.addr,
909 buf_at_from_addr(btr));
910 if (status != BT_BTR_STATUS_OK) {
911 BT_LOGW("Cannot read basic field: "
912 "btr-addr=%p, ft-addr=%p, status=%s",
913 btr, btr->cur_basic_field_type,
914 bt_btr_status_string(status));
915 goto end;
916 }
917
918 consume_bits(btr, field_size);
919
920 if (stack_empty(btr->stack)) {
921 /* Root is a basic type */
922 btr->state = BTR_STATE_DONE;
923 } else {
924 /* Go to next field */
925 stack_top(btr->stack)->index++;
926 btr->state = BTR_STATE_NEXT_FIELD;
927 btr->last_bo = btr->cur_bo;
928 }
929
930 goto end;
931 }
932
933 /* We are here; it means we don't have enough data to decode this */
934 BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer.");
935 stitch_set_from_remaining_buf(btr);
936 btr->state = BTR_STATE_READ_BASIC_CONTINUE;
937 status = BT_BTR_STATUS_EOF;
938
939 end:
940 return status;
941 }
942
943 static inline
944 enum bt_btr_status read_basic_int_type_and_call_begin(
945 struct bt_btr *btr)
946 {
947 return read_basic_type_and_call_begin(btr, read_basic_int_and_call_cb);
948 }
949
950 static inline
951 enum bt_btr_status read_basic_int_type_and_call_continue(
952 struct bt_btr *btr)
953 {
954 return read_basic_type_and_call_continue(btr,
955 read_basic_int_and_call_cb);
956 }
957
958 static inline
959 enum bt_btr_status read_basic_float_type_and_call_begin(
960 struct bt_btr *btr)
961 {
962 return read_basic_type_and_call_begin(btr,
963 read_basic_float_and_call_cb);
964 }
965
966 static inline
967 enum bt_btr_status read_basic_float_type_and_call_continue(
968 struct bt_btr *btr)
969 {
970 return read_basic_type_and_call_continue(btr,
971 read_basic_float_and_call_cb);
972 }
973
974 static inline
975 enum bt_btr_status read_basic_enum_type_and_call_begin(
976 struct bt_btr *btr)
977 {
978 return read_basic_type_and_call_begin(btr,
979 read_basic_enum_and_call_cb);
980 }
981
982 static inline
983 enum bt_btr_status read_basic_enum_type_and_call_continue(
984 struct bt_btr *btr)
985 {
986 return read_basic_type_and_call_continue(btr,
987 read_basic_enum_and_call_cb);
988 }
989
990 static inline
991 enum bt_btr_status read_basic_string_type_and_call(
992 struct bt_btr *btr, bool begin)
993 {
994 size_t buf_at_bytes;
995 const uint8_t *result;
996 size_t available_bytes;
997 const uint8_t *first_chr;
998 enum bt_btr_status status = BT_BTR_STATUS_OK;
999
1000 if (!at_least_one_bit_left(btr)) {
1001 BT_LOGV("Reached end of data: btr-addr=%p", btr);
1002 status = BT_BTR_STATUS_EOF;
1003 goto end;
1004 }
1005
1006 BT_ASSERT(buf_at_from_addr(btr) % 8 == 0);
1007 available_bytes = BITS_TO_BYTES_FLOOR(available_bits(btr));
1008 buf_at_bytes = BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr));
1009 BT_ASSERT(btr->buf.addr);
1010 first_chr = &btr->buf.addr[buf_at_bytes];
1011 result = memchr(first_chr, '\0', available_bytes);
1012
1013 if (begin && btr->user.cbs.types.string_begin) {
1014 BT_LOGV("Calling user function (string, beginning).");
1015 status = btr->user.cbs.types.string_begin(
1016 btr->cur_basic_field_type, btr->user.data);
1017 BT_LOGV("User function returned: status=%s",
1018 bt_btr_status_string(status));
1019 if (status != BT_BTR_STATUS_OK) {
1020 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1021 btr, bt_btr_status_string(status));
1022 goto end;
1023 }
1024 }
1025
1026 if (!result) {
1027 /* No null character yet */
1028 if (btr->user.cbs.types.string) {
1029 BT_LOGV("Calling user function (substring).");
1030 status = btr->user.cbs.types.string(
1031 (const char *) first_chr,
1032 available_bytes, btr->cur_basic_field_type,
1033 btr->user.data);
1034 BT_LOGV("User function returned: status=%s",
1035 bt_btr_status_string(status));
1036 if (status != BT_BTR_STATUS_OK) {
1037 BT_LOGW("User function failed: "
1038 "btr-addr=%p, status=%s",
1039 btr, bt_btr_status_string(status));
1040 goto end;
1041 }
1042 }
1043
1044 consume_bits(btr, BYTES_TO_BITS(available_bytes));
1045 btr->state = BTR_STATE_READ_BASIC_CONTINUE;
1046 status = BT_BTR_STATUS_EOF;
1047 } else {
1048 /* Found the null character */
1049 size_t result_len = (size_t) (result - first_chr);
1050
1051 if (btr->user.cbs.types.string && result_len) {
1052 BT_LOGV("Calling user function (substring).");
1053 status = btr->user.cbs.types.string(
1054 (const char *) first_chr,
1055 result_len, btr->cur_basic_field_type,
1056 btr->user.data);
1057 BT_LOGV("User function returned: status=%s",
1058 bt_btr_status_string(status));
1059 if (status != BT_BTR_STATUS_OK) {
1060 BT_LOGW("User function failed: "
1061 "btr-addr=%p, status=%s",
1062 btr, bt_btr_status_string(status));
1063 goto end;
1064 }
1065 }
1066
1067 if (btr->user.cbs.types.string_end) {
1068 BT_LOGV("Calling user function (string, end).");
1069 status = btr->user.cbs.types.string_end(
1070 btr->cur_basic_field_type, btr->user.data);
1071 BT_LOGV("User function returned: status=%s",
1072 bt_btr_status_string(status));
1073 if (status != BT_BTR_STATUS_OK) {
1074 BT_LOGW("User function failed: "
1075 "btr-addr=%p, status=%s",
1076 btr, bt_btr_status_string(status));
1077 goto end;
1078 }
1079 }
1080
1081 consume_bits(btr, BYTES_TO_BITS(result_len + 1));
1082
1083 if (stack_empty(btr->stack)) {
1084 /* Root is a basic type */
1085 btr->state = BTR_STATE_DONE;
1086 } else {
1087 /* Go to next field */
1088 stack_top(btr->stack)->index++;
1089 btr->state = BTR_STATE_NEXT_FIELD;
1090 btr->last_bo = btr->cur_bo;
1091 }
1092 }
1093
1094 end:
1095 return status;
1096 }
1097
1098 static inline
1099 enum bt_btr_status read_basic_begin_state(struct bt_btr *btr)
1100 {
1101 enum bt_btr_status status;
1102
1103 BT_ASSERT(btr->cur_basic_field_type);
1104
1105 switch (bt_field_type_get_type_id(btr->cur_basic_field_type)) {
1106 case BT_FIELD_TYPE_ID_INTEGER:
1107 status = read_basic_int_type_and_call_begin(btr);
1108 break;
1109 case BT_FIELD_TYPE_ID_FLOAT:
1110 status = read_basic_float_type_and_call_begin(btr);
1111 break;
1112 case BT_FIELD_TYPE_ID_ENUM:
1113 status = read_basic_enum_type_and_call_begin(btr);
1114 break;
1115 case BT_FIELD_TYPE_ID_STRING:
1116 status = read_basic_string_type_and_call(btr, true);
1117 break;
1118 default:
1119 BT_LOGF("Unknown basic field type ID: "
1120 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1121 btr, btr->cur_basic_field_type,
1122 bt_common_field_type_id_string(
1123 bt_field_type_get_type_id(
1124 btr->cur_basic_field_type)));
1125 abort();
1126 }
1127
1128 return status;
1129 }
1130
1131 static inline
1132 enum bt_btr_status read_basic_continue_state(struct bt_btr *btr)
1133 {
1134 enum bt_btr_status status;
1135
1136 BT_ASSERT(btr->cur_basic_field_type);
1137
1138 switch (bt_field_type_get_type_id(btr->cur_basic_field_type)) {
1139 case BT_FIELD_TYPE_ID_INTEGER:
1140 status = read_basic_int_type_and_call_continue(btr);
1141 break;
1142 case BT_FIELD_TYPE_ID_FLOAT:
1143 status = read_basic_float_type_and_call_continue(btr);
1144 break;
1145 case BT_FIELD_TYPE_ID_ENUM:
1146 status = read_basic_enum_type_and_call_continue(btr);
1147 break;
1148 case BT_FIELD_TYPE_ID_STRING:
1149 status = read_basic_string_type_and_call(btr, false);
1150 break;
1151 default:
1152 BT_LOGF("Unknown basic field type ID: "
1153 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1154 btr, btr->cur_basic_field_type,
1155 bt_common_field_type_id_string(
1156 bt_field_type_get_type_id(
1157 btr->cur_basic_field_type)));
1158 abort();
1159 }
1160
1161 return status;
1162 }
1163
1164 static inline
1165 size_t bits_to_skip_to_align_to(struct bt_btr *btr, size_t align)
1166 {
1167 size_t aligned_packet_at;
1168
1169 aligned_packet_at = ALIGN(packet_at(btr), align);
1170 return aligned_packet_at - packet_at(btr);
1171 }
1172
1173 static inline
1174 enum bt_btr_status align_type_state(struct bt_btr *btr,
1175 struct bt_field_type *field_type, enum btr_state next_state)
1176 {
1177 int field_alignment;
1178 size_t skip_bits;
1179 enum bt_btr_status status = BT_BTR_STATUS_OK;
1180
1181 /* Get field's alignment */
1182 field_alignment = bt_field_type_get_alignment(field_type);
1183 if (field_alignment < 0) {
1184 BT_LOGW("Cannot get field type's alignment: "
1185 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1186 btr, field_type,
1187 bt_common_field_type_id_string(
1188 bt_field_type_get_type_id(field_type)));
1189 status = BT_BTR_STATUS_ERROR;
1190 goto end;
1191 }
1192
1193 /*
1194 * 0 means "undefined" for variants; what we really want is 1
1195 * (always aligned)
1196 */
1197 if (field_alignment == 0) {
1198 field_alignment = 1;
1199 }
1200
1201 /* Compute how many bits we need to skip */
1202 skip_bits = bits_to_skip_to_align_to(btr, field_alignment);
1203
1204 /* Nothing to skip? aligned */
1205 if (skip_bits == 0) {
1206 btr->state = next_state;
1207 goto end;
1208 }
1209
1210 /* Make sure there's at least one bit left */
1211 if (!at_least_one_bit_left(btr)) {
1212 status = BT_BTR_STATUS_EOF;
1213 goto end;
1214 }
1215
1216 /* Consume as many bits as possible in what's left */
1217 consume_bits(btr, MIN(available_bits(btr), skip_bits));
1218
1219 /* Are we done now? */
1220 skip_bits = bits_to_skip_to_align_to(btr, field_alignment);
1221 if (skip_bits == 0) {
1222 /* Yes: go to next state */
1223 btr->state = next_state;
1224 goto end;
1225 } else {
1226 /* No: need more data */
1227 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr);
1228 status = BT_BTR_STATUS_EOF;
1229 }
1230
1231 end:
1232 return status;
1233 }
1234
1235 static inline
1236 bool is_compound_type(struct bt_field_type *field_type)
1237 {
1238 enum bt_field_type_id id = bt_field_type_get_type_id(field_type);
1239
1240 return id == BT_FIELD_TYPE_ID_STRUCT || id == BT_FIELD_TYPE_ID_ARRAY ||
1241 id == BT_FIELD_TYPE_ID_SEQUENCE || id == BT_FIELD_TYPE_ID_VARIANT;
1242 }
1243
1244 static inline
1245 enum bt_btr_status next_field_state(struct bt_btr *btr)
1246 {
1247 int ret;
1248 struct stack_entry *top;
1249 struct bt_field_type *next_field_type = NULL;
1250 enum bt_btr_status status = BT_BTR_STATUS_OK;
1251
1252 if (stack_empty(btr->stack)) {
1253 goto end;
1254 }
1255
1256 top = stack_top(btr->stack);
1257
1258 /* Are we done with this base type? */
1259 while (top->index == top->base_len) {
1260 if (btr->user.cbs.types.compound_end) {
1261 BT_LOGV("Calling user function (compound, end).");
1262 status = btr->user.cbs.types.compound_end(
1263 top->base_type, btr->user.data);
1264 BT_LOGV("User function returned: status=%s",
1265 bt_btr_status_string(status));
1266 if (status != BT_BTR_STATUS_OK) {
1267 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1268 btr, bt_btr_status_string(status));
1269 goto end;
1270 }
1271 }
1272
1273 stack_pop(btr->stack);
1274
1275 /* Are we done with the root type? */
1276 if (stack_empty(btr->stack)) {
1277 btr->state = BTR_STATE_DONE;
1278 goto end;
1279 }
1280
1281 top = stack_top(btr->stack);
1282 top->index++;
1283 }
1284
1285 /* Get next field's type */
1286 switch (bt_field_type_get_type_id(top->base_type)) {
1287 case BT_FIELD_TYPE_ID_STRUCT:
1288 ret = bt_field_type_structure_get_field_by_index(
1289 top->base_type, NULL, &next_field_type,
1290 top->index);
1291 if (ret) {
1292 next_field_type = NULL;
1293 }
1294 break;
1295 case BT_FIELD_TYPE_ID_ARRAY:
1296 next_field_type =
1297 bt_field_type_array_get_element_field_type(
1298 top->base_type);
1299 break;
1300 case BT_FIELD_TYPE_ID_SEQUENCE:
1301 next_field_type =
1302 bt_field_type_sequence_get_element_field_type(
1303 top->base_type);
1304 break;
1305 case BT_FIELD_TYPE_ID_VARIANT:
1306 /* Variant types are dynamic: query the user, he should know! */
1307 next_field_type =
1308 btr->user.cbs.query.get_variant_type(
1309 top->base_type, btr->user.data);
1310 break;
1311 default:
1312 break;
1313 }
1314
1315 if (!next_field_type) {
1316 BT_LOGW("Cannot get the field type of the next field: "
1317 "btr-addr=%p, base-ft-addr=%p, base-ft-id=%s, "
1318 "index=%" PRId64,
1319 btr, top->base_type,
1320 bt_common_field_type_id_string(
1321 bt_field_type_get_type_id(top->base_type)),
1322 top->index);
1323 status = BT_BTR_STATUS_ERROR;
1324 goto end;
1325 }
1326
1327 if (is_compound_type(next_field_type)) {
1328 if (btr->user.cbs.types.compound_begin) {
1329 BT_LOGV("Calling user function (compound, begin).");
1330 status = btr->user.cbs.types.compound_begin(
1331 next_field_type, btr->user.data);
1332 BT_LOGV("User function returned: status=%s",
1333 bt_btr_status_string(status));
1334 if (status != BT_BTR_STATUS_OK) {
1335 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1336 btr, bt_btr_status_string(status));
1337 goto end;
1338 }
1339 }
1340
1341 ret = stack_push_with_len(btr, next_field_type);
1342 if (ret) {
1343 /* stack_push_with_len() logs errors */
1344 status = BT_BTR_STATUS_ERROR;
1345 goto end;
1346 }
1347
1348 /* Next state: align a compound type */
1349 btr->state = BTR_STATE_ALIGN_COMPOUND;
1350 } else {
1351 /* Replace current basic field type */
1352 BT_LOGV("Replacing current basic field type: "
1353 "btr-addr=%p, cur-basic-ft-addr=%p, "
1354 "next-basic-ft-addr=%p",
1355 btr, btr->cur_basic_field_type, next_field_type);
1356 BT_MOVE(btr->cur_basic_field_type, next_field_type);
1357
1358 /* Next state: align a basic type */
1359 btr->state = BTR_STATE_ALIGN_BASIC;
1360 }
1361
1362 end:
1363 BT_PUT(next_field_type);
1364
1365 return status;
1366 }
1367
1368 static inline
1369 enum bt_btr_status handle_state(struct bt_btr *btr)
1370 {
1371 enum bt_btr_status status = BT_BTR_STATUS_OK;
1372
1373 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1374 btr, btr_state_string(btr->state));
1375
1376 switch (btr->state) {
1377 case BTR_STATE_NEXT_FIELD:
1378 status = next_field_state(btr);
1379 break;
1380 case BTR_STATE_ALIGN_BASIC:
1381 status = align_type_state(btr, btr->cur_basic_field_type,
1382 BTR_STATE_READ_BASIC_BEGIN);
1383 break;
1384 case BTR_STATE_ALIGN_COMPOUND:
1385 status = align_type_state(btr, stack_top(btr->stack)->base_type,
1386 BTR_STATE_NEXT_FIELD);
1387 break;
1388 case BTR_STATE_READ_BASIC_BEGIN:
1389 status = read_basic_begin_state(btr);
1390 break;
1391 case BTR_STATE_READ_BASIC_CONTINUE:
1392 status = read_basic_continue_state(btr);
1393 break;
1394 case BTR_STATE_DONE:
1395 break;
1396 }
1397
1398 BT_LOGV("Handled state: btr-addr=%p, status=%s",
1399 btr, bt_btr_status_string(status));
1400 return status;
1401 }
1402
1403 struct bt_btr *bt_btr_create(struct bt_btr_cbs cbs, void *data)
1404 {
1405 struct bt_btr *btr;
1406
1407 BT_LOGD_STR("Creating binary type reader (BTR).");
1408 btr = g_new0(struct bt_btr, 1);
1409 if (!btr) {
1410 BT_LOGE_STR("Failed to allocate one binary type reader.");
1411 goto end;
1412 }
1413
1414 btr->stack = stack_new();
1415 if (!btr->stack) {
1416 BT_LOGE_STR("Cannot create BTR's stack.");
1417 bt_btr_destroy(btr);
1418 btr = NULL;
1419 goto end;
1420 }
1421
1422 btr->state = BTR_STATE_NEXT_FIELD;
1423 btr->user.cbs = cbs;
1424 btr->user.data = data;
1425 BT_LOGD("Created BTR: addr=%p", btr);
1426
1427 end:
1428 return btr;
1429 }
1430
1431 void bt_btr_destroy(struct bt_btr *btr)
1432 {
1433 if (btr->stack) {
1434 stack_destroy(btr->stack);
1435 }
1436
1437 BT_LOGD("Destroying BTR: addr=%p", btr);
1438 BT_PUT(btr->cur_basic_field_type);
1439 g_free(btr);
1440 }
1441
1442 static
1443 void reset(struct bt_btr *btr)
1444 {
1445 BT_LOGD("Resetting BTR: addr=%p", btr);
1446 stack_clear(btr->stack);
1447 BT_PUT(btr->cur_basic_field_type);
1448 stitch_reset(btr);
1449 btr->buf.addr = NULL;
1450 btr->last_bo = BT_BYTE_ORDER_UNKNOWN;
1451 }
1452
1453 static
1454 void update_packet_offset(struct bt_btr *btr)
1455 {
1456 BT_LOGV("Updating packet offset for next call: "
1457 "btr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1458 btr, btr->buf.packet_offset,
1459 btr->buf.packet_offset + btr->buf.at);
1460 btr->buf.packet_offset += btr->buf.at;
1461 }
1462
1463 size_t bt_btr_start(struct bt_btr *btr,
1464 struct bt_field_type *type, const uint8_t *buf,
1465 size_t offset, size_t packet_offset, size_t sz,
1466 enum bt_btr_status *status)
1467 {
1468 BT_ASSERT(btr);
1469 BT_ASSERT(BYTES_TO_BITS(sz) >= offset);
1470 reset(btr);
1471 btr->buf.addr = buf;
1472 btr->buf.offset = offset;
1473 btr->buf.at = 0;
1474 btr->buf.packet_offset = packet_offset;
1475 btr->buf.buf_sz = sz;
1476 btr->buf.sz = BYTES_TO_BITS(sz) - offset;
1477 *status = BT_BTR_STATUS_OK;
1478
1479 BT_LOGV("Starting decoding: btr-addr=%p, ft-addr=%p, "
1480 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1481 "packet-offset=%zu",
1482 btr, type, buf, sz, offset, packet_offset);
1483
1484 /* Set root type */
1485 if (is_compound_type(type)) {
1486 /* Compound type: push on visit stack */
1487 int stack_ret;
1488
1489 if (btr->user.cbs.types.compound_begin) {
1490 BT_LOGV("Calling user function (compound, begin).");
1491 *status = btr->user.cbs.types.compound_begin(
1492 type, btr->user.data);
1493 BT_LOGV("User function returned: status=%s",
1494 bt_btr_status_string(*status));
1495 if (*status != BT_BTR_STATUS_OK) {
1496 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1497 btr, bt_btr_status_string(*status));
1498 goto end;
1499 }
1500 }
1501
1502 stack_ret = stack_push_with_len(btr, type);
1503 if (stack_ret) {
1504 /* stack_push_with_len() logs errors */
1505 *status = BT_BTR_STATUS_ERROR;
1506 goto end;
1507 }
1508
1509 btr->state = BTR_STATE_ALIGN_COMPOUND;
1510 } else {
1511 /* Basic type: set as current basic type */
1512 btr->cur_basic_field_type = type;
1513 bt_get(btr->cur_basic_field_type);
1514 btr->state = BTR_STATE_ALIGN_BASIC;
1515 }
1516
1517 /* Run the machine! */
1518 BT_LOGV_STR("Running the state machine.");
1519
1520 while (true) {
1521 *status = handle_state(btr);
1522 if (*status != BT_BTR_STATUS_OK ||
1523 btr->state == BTR_STATE_DONE) {
1524 break;
1525 }
1526 }
1527
1528 /* Update packet offset for next time */
1529 update_packet_offset(btr);
1530
1531 end:
1532 return btr->buf.at;
1533 }
1534
1535 size_t bt_btr_continue(struct bt_btr *btr,
1536 const uint8_t *buf, size_t sz,
1537 enum bt_btr_status *status)
1538 {
1539 BT_ASSERT(btr);
1540 BT_ASSERT(buf);
1541 BT_ASSERT(sz > 0);
1542 btr->buf.addr = buf;
1543 btr->buf.offset = 0;
1544 btr->buf.at = 0;
1545 btr->buf.buf_sz = sz;
1546 btr->buf.sz = BYTES_TO_BITS(sz);
1547 *status = BT_BTR_STATUS_OK;
1548
1549 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1550 btr, buf, sz);
1551
1552 /* Continue running the machine */
1553 BT_LOGV_STR("Running the state machine.");
1554
1555 while (true) {
1556 *status = handle_state(btr);
1557 if (*status != BT_BTR_STATUS_OK ||
1558 btr->state == BTR_STATE_DONE) {
1559 break;
1560 }
1561 }
1562
1563 /* Update packet offset for next time */
1564 update_packet_offset(btr);
1565 return btr->buf.at;
1566 }
This page took 0.090517 seconds and 4 git commands to generate.