2 * Babeltrace - CTF binary type reader (BTR)
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
26 #define BT_LOG_TAG "PLUGIN-CTF-BTR"
35 #include <babeltrace/assert-internal.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>
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)
52 /* A visit stack entry */
55 * Current type of base field, one of:
64 struct bt_field_type
*base_type
;
66 /* Length of base field (always 1 for variant types) */
69 /* Lndex of next field to read */
75 /* Entries (struct stack_entry *) (top is last element) */
82 BTR_STATE_ALIGN_BASIC
,
83 BTR_STATE_ALIGN_COMPOUND
,
84 BTR_STATE_READ_BASIC_BEGIN
,
85 BTR_STATE_READ_BASIC_CONTINUE
,
89 /* Binary type reader */
94 /* Current basic field type */
95 struct bt_field_type
*cur_basic_field_type
;
101 * Last basic field type's byte order.
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.
107 * This is set to BT_BYTE_ORDER_UNKNOWN on reset and when
108 * the last basic field type was a string type.
110 enum bt_byte_order last_bo
;
112 /* Current byte order (copied to last_bo after a successful read) */
113 enum bt_byte_order cur_bo
;
115 /* Stitch buffer infos */
120 /* Offset, within stitch buffer, of first bit */
123 /* Length (bits) of data in stitch buffer from offset */
127 /* User buffer infos */
132 /* Offset of data from address (bits) */
135 /* Current position from offset (bits) */
138 /* Offset of offset within whole packet (bits) */
139 size_t packet_offset
;
141 /* Data size in buffer (bits) */
144 /* Buffer size (bytes) */
150 /* Callback functions */
151 struct bt_btr_cbs cbs
;
159 const char *btr_state_string(enum btr_state 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";
173 return "BTR_STATE_DONE";
180 void stack_entry_free_func(gpointer data
)
182 struct stack_entry
*entry
= data
;
188 struct stack
*stack_new(void)
190 struct stack
*stack
= NULL
;
192 stack
= g_new0(struct stack
, 1);
194 BT_LOGE_STR("Failed to allocate one stack.");
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.");
204 BT_LOGD("Created stack: addr=%p", stack
);
214 void stack_destroy(struct stack
*stack
)
220 BT_LOGD("Destroying stack: addr=%p", stack
);
221 g_ptr_array_free(stack
->entries
, TRUE
);
226 int64_t get_compound_field_type_length(struct bt_btr
*btr
,
227 struct bt_field_type
*field_type
)
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(
236 case BT_FIELD_TYPE_ID_VARIANT
:
237 /* Variant field types always "contain" a single type */
240 case BT_FIELD_TYPE_ID_ARRAY
:
241 length
= bt_field_type_array_get_length(field_type
);
243 case BT_FIELD_TYPE_ID_SEQUENCE
:
244 length
= btr
->user
.cbs
.query
.get_sequence_length(field_type
,
248 BT_LOGW("Cannot get field type's field count: btr-addr=%p, "
249 "ft-addr=%p, ft-id=%s",
251 bt_common_field_type_id_string(
252 bt_field_type_get_type_id(field_type
)));
253 length
= BT_BTR_STATUS_ERROR
;
260 int stack_push(struct stack
*stack
, struct bt_field_type
*base_type
,
264 struct stack_entry
*entry
;
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);
276 BT_LOGE("Failed to allocate one stack entry: stack-addr=%p",
278 ret
= BT_BTR_STATUS_ERROR
;
282 entry
->base_type
= base_type
;
283 entry
->base_len
= base_len
;
284 g_ptr_array_add(stack
->entries
, entry
);
291 int stack_push_with_len(struct bt_btr
*btr
,
292 struct bt_field_type
*base_type
)
295 int64_t base_len
= get_compound_field_type_length(btr
, base_type
);
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
;
306 ret
= stack_push(btr
->stack
, base_type
, (size_t) base_len
);
313 unsigned int stack_size(struct stack
*stack
)
316 return stack
->entries
->len
;
320 void stack_pop(struct stack
*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);
331 bool stack_empty(struct stack
*stack
)
333 return stack_size(stack
) == 0;
337 void stack_clear(struct stack
*stack
)
341 if (!stack_empty(stack
)) {
342 g_ptr_array_remove_range(stack
->entries
, 0, stack_size(stack
));
345 BT_ASSERT(stack_empty(stack
));
349 struct stack_entry
*stack_top(struct stack
*stack
)
352 BT_ASSERT(stack_size(stack
));
354 return g_ptr_array_index(stack
->entries
, stack
->entries
->len
- 1);
358 size_t available_bits(struct bt_btr
*btr
)
360 return btr
->buf
.sz
- btr
->buf
.at
;
364 void consume_bits(struct bt_btr
*btr
, size_t incr
)
366 BT_LOGV("Advancing cursor: btr-addr=%p, cur-before=%zu, cur-after=%zu",
367 btr
, btr
->buf
.at
, btr
->buf
.at
+ incr
);
372 bool has_enough_bits(struct bt_btr
*btr
, size_t sz
)
374 return available_bits(btr
) >= sz
;
378 bool at_least_one_bit_left(struct bt_btr
*btr
)
380 return has_enough_bits(btr
, 1);
384 size_t packet_at(struct bt_btr
*btr
)
386 return btr
->buf
.packet_offset
+ btr
->buf
.at
;
390 size_t buf_at_from_addr(struct bt_btr
*btr
)
395 * ====== offset ===== (17)
397 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
399 * addr (0) ==== at ==== (12)
403 * =============================== (29)
405 return btr
->buf
.offset
+ btr
->buf
.at
;
409 int get_basic_field_type_size(struct bt_btr
*btr
,
410 struct bt_field_type
*field_type
)
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
);
418 case BT_FIELD_TYPE_ID_FLOAT
:
420 int exp_dig
, mant_dig
;
423 bt_field_type_floating_point_get_exponent_digits(
426 bt_field_type_floating_point_get_mantissa_digits(
428 BT_ASSERT(exp_dig
>= 0);
429 BT_ASSERT(mant_dig
>= 0);
430 size
= exp_dig
+ mant_dig
;
433 case BT_FIELD_TYPE_ID_ENUM
:
435 struct bt_field_type
*int_type
;
438 bt_field_type_enumeration_borrow_container_field_type(
441 size
= get_basic_field_type_size(btr
, int_type
);
445 size
= BT_BTR_STATUS_ERROR
;
453 void stitch_reset(struct bt_btr
*btr
)
455 btr
->stitch
.offset
= 0;
460 size_t stitch_at_from_addr(struct bt_btr
*btr
)
462 return btr
->stitch
.offset
+ btr
->stitch
.at
;
466 void stitch_append_from_buf(struct bt_btr
*btr
, size_t sz
)
468 size_t 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
],
484 btr
->stitch
.at
+= sz
;
485 consume_bits(btr
, sz
);
489 void stitch_append_from_remaining_buf(struct bt_btr
*btr
)
491 stitch_append_from_buf(btr
, available_bits(btr
));
495 void stitch_set_from_remaining_buf(struct bt_btr
*btr
)
498 btr
->stitch
.offset
= IN_BYTE_OFFSET(buf_at_from_addr(btr
));
499 stitch_append_from_remaining_buf(btr
);
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
)
506 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
);
513 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
514 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
517 BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo
);
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
);
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
)
531 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
);
538 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
539 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
542 BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo
);
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
);
552 typedef enum bt_btr_status (* read_basic_and_call_cb_t
)(struct bt_btr
*,
553 const uint8_t *, size_t);
556 enum bt_btr_status
validate_contiguous_bo(struct bt_btr
*btr
,
557 enum bt_byte_order next_bo
)
559 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
561 /* Always valid when at a byte boundary */
562 if (packet_at(btr
) % 8 == 0) {
566 /* Always valid if last byte order is unknown */
567 if (btr
->last_bo
== BT_BYTE_ORDER_UNKNOWN
) {
571 /* Always valid if next byte order is unknown */
572 if (next_bo
== BT_BYTE_ORDER_UNKNOWN
) {
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
;
585 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
586 if (next_bo
!= BT_BYTE_ORDER_LITTLE_ENDIAN
) {
587 status
= BT_BTR_STATUS_ERROR
;
591 status
= BT_BTR_STATUS_ERROR
;
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
));
606 enum bt_btr_status
read_basic_float_and_call_cb(struct bt_btr
*btr
,
607 const uint8_t *buf
, size_t at
)
612 enum bt_byte_order bo
;
613 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
);
619 switch (field_size
) {
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
);
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
));
642 f32
.u
= (uint32_t) v
;
643 dblval
= (double) f32
.f
;
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
,
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
));
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: "
675 status
= BT_BTR_STATUS_ERROR
;
679 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
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
));
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
)
706 enum bt_byte_order bo
;
707 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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",
715 status
= BT_BTR_STATUS_ERROR
;
719 bo
= bt_field_type_get_byte_order(int_type
);
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.
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
));
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
));
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
));
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
));
781 enum bt_btr_status
read_basic_int_and_call_cb(struct bt_btr
*btr
,
782 const uint8_t *buf
, size_t at
)
784 return read_basic_int_and_call(btr
, buf
, at
, btr
->cur_basic_field_type
,
785 btr
->cur_basic_field_type
);
789 enum bt_btr_status
read_basic_enum_and_call_cb(struct bt_btr
*btr
,
790 const uint8_t *buf
, size_t at
)
792 struct bt_field_type
*int_field_type
;
793 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
);
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
)
810 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
;
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
;
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
,
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
));
846 if (stack_empty(btr
->stack
)) {
847 /* Root is a basic type */
848 btr
->state
= BTR_STATE_DONE
;
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
;
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
;
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
)
873 enum bt_byte_order bo
;
874 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
;
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
;
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 */
898 available
= available_bits(btr
);
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
));
913 consume_bits(btr
, field_size
);
915 if (stack_empty(btr
->stack
)) {
916 /* Root is a basic type */
917 btr
->state
= BTR_STATE_DONE
;
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
;
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
;
939 enum bt_btr_status
read_basic_int_type_and_call_begin(
942 return read_basic_type_and_call_begin(btr
, read_basic_int_and_call_cb
);
946 enum bt_btr_status
read_basic_int_type_and_call_continue(
949 return read_basic_type_and_call_continue(btr
,
950 read_basic_int_and_call_cb
);
954 enum bt_btr_status
read_basic_float_type_and_call_begin(
957 return read_basic_type_and_call_begin(btr
,
958 read_basic_float_and_call_cb
);
962 enum bt_btr_status
read_basic_float_type_and_call_continue(
965 return read_basic_type_and_call_continue(btr
,
966 read_basic_float_and_call_cb
);
970 enum bt_btr_status
read_basic_enum_type_and_call_begin(
973 return read_basic_type_and_call_begin(btr
,
974 read_basic_enum_and_call_cb
);
978 enum bt_btr_status
read_basic_enum_type_and_call_continue(
981 return read_basic_type_and_call_continue(btr
,
982 read_basic_enum_and_call_cb
);
986 enum bt_btr_status
read_basic_string_type_and_call(
987 struct bt_btr
*btr
, bool begin
)
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
;
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
;
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
);
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
));
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
,
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
));
1039 consume_bits(btr
, BYTES_TO_BITS(available_bytes
));
1040 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
1041 status
= BT_BTR_STATUS_EOF
;
1043 /* Found the null character */
1044 size_t result_len
= (size_t) (result
- first_chr
);
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
,
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
));
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
));
1076 consume_bits(btr
, BYTES_TO_BITS(result_len
+ 1));
1078 if (stack_empty(btr
->stack
)) {
1079 /* Root is a basic type */
1080 btr
->state
= BTR_STATE_DONE
;
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
;
1094 enum bt_btr_status
read_basic_begin_state(struct bt_btr
*btr
)
1096 enum bt_btr_status status
;
1098 BT_ASSERT(btr
->cur_basic_field_type
);
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
);
1104 case BT_FIELD_TYPE_ID_FLOAT
:
1105 status
= read_basic_float_type_and_call_begin(btr
);
1107 case BT_FIELD_TYPE_ID_ENUM
:
1108 status
= read_basic_enum_type_and_call_begin(btr
);
1110 case BT_FIELD_TYPE_ID_STRING
:
1111 status
= read_basic_string_type_and_call(btr
, true);
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
)));
1127 enum bt_btr_status
read_basic_continue_state(struct bt_btr
*btr
)
1129 enum bt_btr_status status
;
1131 BT_ASSERT(btr
->cur_basic_field_type
);
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
);
1137 case BT_FIELD_TYPE_ID_FLOAT
:
1138 status
= read_basic_float_type_and_call_continue(btr
);
1140 case BT_FIELD_TYPE_ID_ENUM
:
1141 status
= read_basic_enum_type_and_call_continue(btr
);
1143 case BT_FIELD_TYPE_ID_STRING
:
1144 status
= read_basic_string_type_and_call(btr
, false);
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
)));
1160 size_t bits_to_skip_to_align_to(struct bt_btr
*btr
, size_t align
)
1162 size_t aligned_packet_at
;
1164 aligned_packet_at
= ALIGN(packet_at(btr
), align
);
1165 return aligned_packet_at
- packet_at(btr
);
1169 enum bt_btr_status
align_type_state(struct bt_btr
*btr
,
1170 struct bt_field_type
*field_type
, enum btr_state next_state
)
1172 int field_alignment
;
1174 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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",
1182 bt_common_field_type_id_string(
1183 bt_field_type_get_type_id(field_type
)));
1184 status
= BT_BTR_STATUS_ERROR
;
1189 * 0 means "undefined" for variants; what we really want is 1
1192 if (field_alignment
== 0) {
1193 field_alignment
= 1;
1196 /* Compute how many bits we need to skip */
1197 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1199 /* Nothing to skip? aligned */
1200 if (skip_bits
== 0) {
1201 btr
->state
= next_state
;
1205 /* Make sure there's at least one bit left */
1206 if (!at_least_one_bit_left(btr
)) {
1207 status
= BT_BTR_STATUS_EOF
;
1211 /* Consume as many bits as possible in what's left */
1212 consume_bits(btr
, MIN(available_bits(btr
), skip_bits
));
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
;
1221 /* No: need more data */
1222 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr
);
1223 status
= BT_BTR_STATUS_EOF
;
1231 bool is_compound_type(struct bt_field_type
*field_type
)
1233 enum bt_field_type_id id
= bt_field_type_get_type_id(field_type
);
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
;
1240 enum bt_btr_status
next_field_state(struct bt_btr
*btr
)
1243 struct stack_entry
*top
;
1244 struct bt_field_type
*next_field_type
= NULL
;
1245 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1247 if (stack_empty(btr
->stack
)) {
1251 top
= stack_top(btr
->stack
);
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
));
1268 stack_pop(btr
->stack
);
1270 /* Are we done with the root type? */
1271 if (stack_empty(btr
->stack
)) {
1272 btr
->state
= BTR_STATE_DONE
;
1276 top
= stack_top(btr
->stack
);
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
,
1287 next_field_type
= NULL
;
1290 case BT_FIELD_TYPE_ID_ARRAY
:
1292 bt_field_type_array_borrow_element_field_type(
1295 case BT_FIELD_TYPE_ID_SEQUENCE
:
1297 bt_field_type_sequence_borrow_element_field_type(
1300 case BT_FIELD_TYPE_ID_VARIANT
:
1301 /* Variant types are dynamic: query the user, he should know! */
1303 btr
->user
.cbs
.query
.borrow_variant_field_type(
1304 top
->base_type
, btr
->user
.data
);
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, "
1314 btr
, top
->base_type
,
1315 bt_common_field_type_id_string(
1316 bt_field_type_get_type_id(top
->base_type
)),
1318 status
= BT_BTR_STATUS_ERROR
;
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
));
1336 ret
= stack_push_with_len(btr
, next_field_type
);
1338 /* stack_push_with_len() logs errors */
1339 status
= BT_BTR_STATUS_ERROR
;
1343 /* Next state: align a compound type */
1344 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
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
;
1353 /* Next state: align a basic type */
1354 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1362 enum bt_btr_status
handle_state(struct bt_btr
*btr
)
1364 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1366 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1367 btr
, btr_state_string(btr
->state
));
1369 switch (btr
->state
) {
1370 case BTR_STATE_NEXT_FIELD
:
1371 status
= next_field_state(btr
);
1373 case BTR_STATE_ALIGN_BASIC
:
1374 status
= align_type_state(btr
, btr
->cur_basic_field_type
,
1375 BTR_STATE_READ_BASIC_BEGIN
);
1377 case BTR_STATE_ALIGN_COMPOUND
:
1378 status
= align_type_state(btr
, stack_top(btr
->stack
)->base_type
,
1379 BTR_STATE_NEXT_FIELD
);
1381 case BTR_STATE_READ_BASIC_BEGIN
:
1382 status
= read_basic_begin_state(btr
);
1384 case BTR_STATE_READ_BASIC_CONTINUE
:
1385 status
= read_basic_continue_state(btr
);
1387 case BTR_STATE_DONE
:
1391 BT_LOGV("Handled state: btr-addr=%p, status=%s",
1392 btr
, bt_btr_status_string(status
));
1396 struct bt_btr
*bt_btr_create(struct bt_btr_cbs cbs
, void *data
)
1400 BT_LOGD_STR("Creating binary type reader (BTR).");
1401 btr
= g_new0(struct bt_btr
, 1);
1403 BT_LOGE_STR("Failed to allocate one binary type reader.");
1407 btr
->stack
= stack_new();
1409 BT_LOGE_STR("Cannot create BTR's stack.");
1410 bt_btr_destroy(btr
);
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
);
1424 void bt_btr_destroy(struct bt_btr
*btr
)
1427 stack_destroy(btr
->stack
);
1430 BT_LOGD("Destroying BTR: addr=%p", btr
);
1435 void reset(struct bt_btr
*btr
)
1437 BT_LOGD("Resetting BTR: addr=%p", btr
);
1438 stack_clear(btr
->stack
);
1440 btr
->buf
.addr
= NULL
;
1441 btr
->last_bo
= BT_BYTE_ORDER_UNKNOWN
;
1445 void update_packet_offset(struct bt_btr
*btr
)
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
;
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
)
1460 BT_ASSERT(BYTES_TO_BITS(sz
) >= offset
);
1462 btr
->buf
.addr
= buf
;
1463 btr
->buf
.offset
= offset
;
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
;
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
);
1476 if (is_compound_type(type
)) {
1477 /* Compound type: push on visit stack */
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
));
1493 stack_ret
= stack_push_with_len(btr
, type
);
1495 /* stack_push_with_len() logs errors */
1496 *status
= BT_BTR_STATUS_ERROR
;
1500 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
1502 /* Basic type: set as current basic type */
1503 btr
->cur_basic_field_type
= type
;
1504 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1507 /* Run the machine! */
1508 BT_LOGV_STR("Running the state machine.");
1511 *status
= handle_state(btr
);
1512 if (*status
!= BT_BTR_STATUS_OK
||
1513 btr
->state
== BTR_STATE_DONE
) {
1518 /* Update packet offset for next time */
1519 update_packet_offset(btr
);
1525 size_t bt_btr_continue(struct bt_btr
*btr
,
1526 const uint8_t *buf
, size_t sz
,
1527 enum bt_btr_status
*status
)
1532 btr
->buf
.addr
= buf
;
1533 btr
->buf
.offset
= 0;
1535 btr
->buf
.buf_sz
= sz
;
1536 btr
->buf
.sz
= BYTES_TO_BITS(sz
);
1537 *status
= BT_BTR_STATUS_OK
;
1539 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1542 /* Continue running the machine */
1543 BT_LOGV_STR("Running the state machine.");
1546 *status
= handle_state(btr
);
1547 if (*status
!= BT_BTR_STATUS_OK
||
1548 btr
->state
== BTR_STATE_DONE
) {
1553 /* Update packet offset for next time */
1554 update_packet_offset(btr
);