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:
62 struct bt_field_type
*base_type
;
64 /* Length of base field (always 1 for variant types) */
67 /* Lndex of next field to read */
73 /* Entries (struct stack_entry) */
76 /* Number of active entries */
83 BTR_STATE_ALIGN_BASIC
,
84 BTR_STATE_ALIGN_COMPOUND
,
85 BTR_STATE_READ_BASIC_BEGIN
,
86 BTR_STATE_READ_BASIC_CONTINUE
,
90 /* Binary type reader */
95 /* Current basic field type */
96 struct bt_field_type
*cur_basic_field_type
;
102 * Last basic field type's byte order.
104 * This is used to detect errors since two contiguous basic
105 * types for which the common boundary is not the boundary of
106 * a byte cannot have different byte orders.
108 * This is set to BT_BYTE_ORDER_UNKNOWN on reset and when
109 * the last basic field type was a string type.
111 enum bt_byte_order last_bo
;
113 /* Current byte order (copied to last_bo after a successful read) */
114 enum bt_byte_order cur_bo
;
116 /* Stitch buffer infos */
121 /* Offset, within stitch buffer, of first bit */
124 /* Length (bits) of data in stitch buffer from offset */
128 /* User buffer infos */
133 /* Offset of data from address (bits) */
136 /* Current position from offset (bits) */
139 /* Offset of offset within whole packet (bits) */
140 size_t packet_offset
;
142 /* Data size in buffer (bits) */
145 /* Buffer size (bytes) */
151 /* Callback functions */
152 struct bt_btr_cbs cbs
;
160 const char *btr_state_string(enum btr_state state
)
163 case BTR_STATE_NEXT_FIELD
:
164 return "BTR_STATE_NEXT_FIELD";
165 case BTR_STATE_ALIGN_BASIC
:
166 return "BTR_STATE_ALIGN_BASIC";
167 case BTR_STATE_ALIGN_COMPOUND
:
168 return "BTR_STATE_ALIGN_COMPOUND";
169 case BTR_STATE_READ_BASIC_BEGIN
:
170 return "BTR_STATE_READ_BASIC_BEGIN";
171 case BTR_STATE_READ_BASIC_CONTINUE
:
172 return "BTR_STATE_READ_BASIC_CONTINUE";
174 return "BTR_STATE_DONE";
181 struct stack
*stack_new(void)
183 struct stack
*stack
= NULL
;
185 stack
= g_new0(struct stack
, 1);
187 BT_LOGE_STR("Failed to allocate one stack.");
191 stack
->entries
= g_array_new(FALSE
, TRUE
, sizeof(struct stack_entry
));
192 if (!stack
->entries
) {
193 BT_LOGE_STR("Failed to allocate a GArray.");
197 BT_LOGD("Created stack: addr=%p", stack
);
206 void stack_destroy(struct stack
*stack
)
212 BT_LOGD("Destroying stack: addr=%p", stack
);
214 if (stack
->entries
) {
215 g_array_free(stack
->entries
, TRUE
);
222 int64_t get_compound_field_type_length(struct bt_btr
*btr
,
223 struct bt_field_type
*field_type
)
227 switch (bt_field_type_get_type_id(field_type
)) {
228 case BT_FIELD_TYPE_ID_STRUCT
:
229 length
= (int64_t) bt_field_type_structure_get_field_count(
232 case BT_FIELD_TYPE_ID_VARIANT
:
233 /* Variant field types always "contain" a single type */
236 case BT_FIELD_TYPE_ID_ARRAY
:
237 length
= bt_field_type_array_get_length(field_type
);
239 case BT_FIELD_TYPE_ID_SEQUENCE
:
240 length
= btr
->user
.cbs
.query
.get_sequence_length(field_type
,
244 BT_LOGW("Cannot get field type's field count: btr-addr=%p, "
245 "ft-addr=%p, ft-id=%s",
247 bt_common_field_type_id_string(
248 bt_field_type_get_type_id(field_type
)));
249 length
= BT_BTR_STATUS_ERROR
;
256 int stack_push(struct stack
*stack
, struct bt_field_type
*base_type
,
259 struct stack_entry
*entry
;
262 BT_ASSERT(base_type
);
263 BT_LOGV("Pushing field type on stack: stack-addr=%p, "
264 "ft-addr=%p, ft-id=%s, base-length=%zu, "
265 "stack-size-before=%zu, stack-size-after=%zu",
266 stack
, base_type
, bt_common_field_type_id_string(
267 bt_field_type_get_type_id(base_type
)),
268 base_len
, stack
->size
, stack
->size
+ 1);
270 if (stack
->entries
->len
== stack
->size
) {
271 g_array_set_size(stack
->entries
, stack
->size
+ 1);
274 entry
= &g_array_index(stack
->entries
, struct stack_entry
, stack
->size
);
275 entry
->base_type
= base_type
;
276 entry
->base_len
= base_len
;
283 int stack_push_with_len(struct bt_btr
*btr
,
284 struct bt_field_type
*base_type
)
287 int64_t base_len
= get_compound_field_type_length(btr
, base_type
);
290 BT_LOGW("Cannot get compound field type's field count: "
291 "btr-addr=%p, ft-addr=%p, ft-id=%s",
292 btr
, base_type
, bt_common_field_type_id_string(
293 bt_field_type_get_type_id(base_type
)));
294 ret
= BT_BTR_STATUS_ERROR
;
298 ret
= stack_push(btr
->stack
, base_type
, (size_t) base_len
);
305 unsigned int stack_size(struct stack
*stack
)
312 void stack_pop(struct stack
*stack
)
315 BT_ASSERT(stack_size(stack
));
316 BT_LOGV("Popping from stack: "
317 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
318 stack
, stack
->entries
->len
, stack
->entries
->len
- 1);
323 bool stack_empty(struct stack
*stack
)
325 return stack_size(stack
) == 0;
329 void stack_clear(struct stack
*stack
)
336 struct stack_entry
*stack_top(struct stack
*stack
)
339 BT_ASSERT(stack_size(stack
));
340 return &g_array_index(stack
->entries
, struct stack_entry
,
345 size_t available_bits(struct bt_btr
*btr
)
347 return btr
->buf
.sz
- btr
->buf
.at
;
351 void consume_bits(struct bt_btr
*btr
, size_t incr
)
353 BT_LOGV("Advancing cursor: btr-addr=%p, cur-before=%zu, cur-after=%zu",
354 btr
, btr
->buf
.at
, btr
->buf
.at
+ incr
);
359 bool has_enough_bits(struct bt_btr
*btr
, size_t sz
)
361 return available_bits(btr
) >= sz
;
365 bool at_least_one_bit_left(struct bt_btr
*btr
)
367 return has_enough_bits(btr
, 1);
371 size_t packet_at(struct bt_btr
*btr
)
373 return btr
->buf
.packet_offset
+ btr
->buf
.at
;
377 size_t buf_at_from_addr(struct bt_btr
*btr
)
382 * ====== offset ===== (17)
384 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
386 * addr (0) ==== at ==== (12)
390 * =============================== (29)
392 return btr
->buf
.offset
+ btr
->buf
.at
;
396 int get_basic_field_type_size(struct bt_btr
*btr
,
397 struct bt_field_type
*field_type
)
401 switch (bt_field_type_get_type_id(field_type
)) {
402 case BT_FIELD_TYPE_ID_INTEGER
:
403 size
= bt_field_type_integer_get_size(field_type
);
405 case BT_FIELD_TYPE_ID_FLOAT
:
407 int exp_dig
, mant_dig
;
410 bt_field_type_floating_point_get_exponent_digits(
413 bt_field_type_floating_point_get_mantissa_digits(
415 BT_ASSERT(exp_dig
>= 0);
416 BT_ASSERT(mant_dig
>= 0);
417 size
= exp_dig
+ mant_dig
;
420 case BT_FIELD_TYPE_ID_ENUM
:
422 struct bt_field_type
*int_type
;
425 bt_field_type_enumeration_borrow_container_field_type(
428 size
= get_basic_field_type_size(btr
, int_type
);
432 size
= BT_BTR_STATUS_ERROR
;
440 void stitch_reset(struct bt_btr
*btr
)
442 btr
->stitch
.offset
= 0;
447 size_t stitch_at_from_addr(struct bt_btr
*btr
)
449 return btr
->stitch
.offset
+ btr
->stitch
.at
;
453 void stitch_append_from_buf(struct bt_btr
*btr
, size_t sz
)
455 size_t stitch_byte_at
;
464 BITS_TO_BYTES_FLOOR(stitch_at_from_addr(btr
));
465 buf_byte_at
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr
));
466 nb_bytes
= BITS_TO_BYTES_CEIL(sz
);
467 BT_ASSERT(nb_bytes
> 0);
468 BT_ASSERT(btr
->buf
.addr
);
469 memcpy(&btr
->stitch
.buf
[stitch_byte_at
], &btr
->buf
.addr
[buf_byte_at
],
471 btr
->stitch
.at
+= sz
;
472 consume_bits(btr
, sz
);
476 void stitch_append_from_remaining_buf(struct bt_btr
*btr
)
478 stitch_append_from_buf(btr
, available_bits(btr
));
482 void stitch_set_from_remaining_buf(struct bt_btr
*btr
)
485 btr
->stitch
.offset
= IN_BYTE_OFFSET(buf_at_from_addr(btr
));
486 stitch_append_from_remaining_buf(btr
);
490 enum bt_btr_status
read_unsigned_bitfield(const uint8_t *buf
, size_t at
,
491 int64_t field_size
, enum bt_byte_order bo
, uint64_t *v
)
493 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
496 case BT_BYTE_ORDER_BIG_ENDIAN
:
497 case BT_BYTE_ORDER_NETWORK
:
498 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
500 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
501 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
504 BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo
);
508 BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64
", "
509 "bo=%s, val=%" PRIu64
, at
, field_size
,
510 bt_common_byte_order_string(bo
), *v
);
515 enum bt_btr_status
read_signed_bitfield(const uint8_t *buf
, size_t at
,
516 int64_t field_size
, enum bt_byte_order bo
, int64_t *v
)
518 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
521 case BT_BYTE_ORDER_BIG_ENDIAN
:
522 case BT_BYTE_ORDER_NETWORK
:
523 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
525 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
526 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
529 BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo
);
533 BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64
", "
534 "bo=%s, val=%" PRId64
, at
, field_size
,
535 bt_common_byte_order_string(bo
), *v
);
539 typedef enum bt_btr_status (* read_basic_and_call_cb_t
)(struct bt_btr
*,
540 const uint8_t *, size_t);
543 enum bt_btr_status
validate_contiguous_bo(struct bt_btr
*btr
,
544 enum bt_byte_order next_bo
)
546 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
548 /* Always valid when at a byte boundary */
549 if (packet_at(btr
) % 8 == 0) {
553 /* Always valid if last byte order is unknown */
554 if (btr
->last_bo
== BT_BYTE_ORDER_UNKNOWN
) {
558 /* Always valid if next byte order is unknown */
559 if (next_bo
== BT_BYTE_ORDER_UNKNOWN
) {
563 /* Make sure last byte order is compatible with the next byte order */
564 switch (btr
->last_bo
) {
565 case BT_BYTE_ORDER_BIG_ENDIAN
:
566 case BT_BYTE_ORDER_NETWORK
:
567 if (next_bo
!= BT_BYTE_ORDER_BIG_ENDIAN
&&
568 next_bo
!= BT_BYTE_ORDER_NETWORK
) {
569 status
= BT_BTR_STATUS_ERROR
;
572 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
573 if (next_bo
!= BT_BYTE_ORDER_LITTLE_ENDIAN
) {
574 status
= BT_BTR_STATUS_ERROR
;
578 status
= BT_BTR_STATUS_ERROR
;
583 BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
584 "btr-addr=%p, last-bo=%s, next-bo=%s",
585 btr
, bt_common_byte_order_string(btr
->last_bo
),
586 bt_common_byte_order_string(next_bo
));
593 enum bt_btr_status
read_basic_float_and_call_cb(struct bt_btr
*btr
,
594 const uint8_t *buf
, size_t at
)
599 enum bt_byte_order bo
;
600 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
602 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
603 bo
= bt_field_type_get_byte_order(btr
->cur_basic_field_type
);
606 switch (field_size
) {
615 ret
= bt_field_type_floating_point_get_mantissa_digits(
616 btr
->cur_basic_field_type
);
617 BT_ASSERT(ret
== 24);
618 ret
= bt_field_type_floating_point_get_exponent_digits(
619 btr
->cur_basic_field_type
);
621 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
, &v
);
622 if (status
!= BT_BTR_STATUS_OK
) {
623 BT_LOGW("Cannot read unsigned 32-bit bit array for floating point number field: "
624 "btr-addr=%p, status=%s",
625 btr
, bt_btr_status_string(status
));
629 f32
.u
= (uint32_t) v
;
630 dblval
= (double) f32
.f
;
640 ret
= bt_field_type_floating_point_get_mantissa_digits(
641 btr
->cur_basic_field_type
);
642 BT_ASSERT(ret
== 53);
643 ret
= bt_field_type_floating_point_get_exponent_digits(
644 btr
->cur_basic_field_type
);
645 BT_ASSERT(ret
== 11);
646 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
,
648 if (status
!= BT_BTR_STATUS_OK
) {
649 BT_LOGW("Cannot read unsigned 64-bit bit array for floating point number field: "
650 "btr-addr=%p, status=%s",
651 btr
, bt_btr_status_string(status
));
659 /* Only 32-bit and 64-bit fields are supported currently */
660 BT_LOGW("Only 32-bit and 64-bit floating point number fields are supported: "
662 status
= BT_BTR_STATUS_ERROR
;
666 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
669 if (btr
->user
.cbs
.types
.floating_point
) {
670 BT_LOGV("Calling user function (floating point number).");
671 status
= btr
->user
.cbs
.types
.floating_point(dblval
,
672 btr
->cur_basic_field_type
, btr
->user
.data
);
673 BT_LOGV("User function returned: status=%s",
674 bt_btr_status_string(status
));
675 if (status
!= BT_BTR_STATUS_OK
) {
676 BT_LOGW("User function failed: btr-addr=%p, status=%s",
677 btr
, bt_btr_status_string(status
));
686 enum bt_btr_status
read_basic_int_and_call(struct bt_btr
*btr
,
687 const uint8_t *buf
, size_t at
,
688 struct bt_field_type
*int_type
,
689 struct bt_field_type
*orig_type
)
693 enum bt_byte_order bo
;
694 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
696 signd
= bt_field_type_integer_is_signed(int_type
);
697 field_size
= get_basic_field_type_size(btr
, int_type
);
698 if (field_size
< 1) {
699 BT_LOGW("Cannot get integer field type's size: "
700 "btr=%p, at=%zu, ft-addr=%p",
702 status
= BT_BTR_STATUS_ERROR
;
706 bo
= bt_field_type_get_byte_order(int_type
);
709 * Update current byte order now because we could be reading
710 * the integer value of an enumeration type, and thus we know
711 * here the actual supporting integer type's byte order.
718 status
= read_signed_bitfield(buf
, at
, field_size
, bo
, &v
);
719 if (status
!= BT_BTR_STATUS_OK
) {
720 BT_LOGW("Cannot read signed bit array for signed integer field: "
721 "btr-addr=%p, status=%s",
722 btr
, bt_btr_status_string(status
));
726 if (btr
->user
.cbs
.types
.signed_int
) {
727 BT_LOGV("Calling user function (signed integer).");
728 status
= btr
->user
.cbs
.types
.signed_int(v
,
729 btr
->cur_basic_field_type
, btr
->user
.data
);
730 BT_LOGV("User function returned: status=%s",
731 bt_btr_status_string(status
));
732 if (status
!= BT_BTR_STATUS_OK
) {
733 BT_LOGW("User function failed: "
734 "btr-addr=%p, status=%s",
735 btr
, bt_btr_status_string(status
));
741 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
, &v
);
742 if (status
!= BT_BTR_STATUS_OK
) {
743 BT_LOGW("Cannot read unsigned bit array for unsigned integer field: "
744 "btr-addr=%p, status=%s",
745 btr
, bt_btr_status_string(status
));
749 if (btr
->user
.cbs
.types
.unsigned_int
) {
750 BT_LOGV("Calling user function (unsigned integer).");
751 status
= btr
->user
.cbs
.types
.unsigned_int(v
,
752 btr
->cur_basic_field_type
, btr
->user
.data
);
753 BT_LOGV("User function returned: status=%s",
754 bt_btr_status_string(status
));
755 if (status
!= BT_BTR_STATUS_OK
) {
756 BT_LOGW("User function failed: "
757 "btr-addr=%p, status=%s",
758 btr
, bt_btr_status_string(status
));
768 enum bt_btr_status
read_basic_int_and_call_cb(struct bt_btr
*btr
,
769 const uint8_t *buf
, size_t at
)
771 return read_basic_int_and_call(btr
, buf
, at
, btr
->cur_basic_field_type
,
772 btr
->cur_basic_field_type
);
776 enum bt_btr_status
read_basic_enum_and_call_cb(struct bt_btr
*btr
,
777 const uint8_t *buf
, size_t at
)
779 struct bt_field_type
*int_field_type
;
780 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
782 int_field_type
= bt_field_type_enumeration_borrow_container_field_type(
783 btr
->cur_basic_field_type
);
784 BT_ASSERT(int_field_type
);
785 status
= read_basic_int_and_call(btr
, buf
, at
,
786 int_field_type
, btr
->cur_basic_field_type
);
791 enum bt_btr_status
read_basic_type_and_call_continue(struct bt_btr
*btr
,
792 read_basic_and_call_cb_t read_basic_and_call_cb
)
797 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
799 if (!at_least_one_bit_left(btr
)) {
800 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
801 status
= BT_BTR_STATUS_EOF
;
805 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
806 if (field_size
< 1) {
807 BT_LOGW("Cannot get basic field type's size: "
808 "btr-addr=%p, ft-addr=%p",
809 btr
, btr
->cur_basic_field_type
);
810 status
= BT_BTR_STATUS_ERROR
;
814 available
= available_bits(btr
);
815 needed_bits
= field_size
- btr
->stitch
.at
;
816 BT_LOGV("Continuing basic field decoding: "
817 "btr-addr=%p, field-size=%" PRId64
", needed-size=%" PRId64
", "
818 "available-size=%zu",
819 btr
, field_size
, needed_bits
, available
);
820 if (needed_bits
<= available
) {
821 /* We have all the bits; append to stitch, then decode */
822 stitch_append_from_buf(btr
, needed_bits
);
823 status
= read_basic_and_call_cb(btr
, btr
->stitch
.buf
,
825 if (status
!= BT_BTR_STATUS_OK
) {
826 BT_LOGW("Cannot read basic field: "
827 "btr-addr=%p, ft-addr=%p, status=%s",
828 btr
, btr
->cur_basic_field_type
,
829 bt_btr_status_string(status
));
833 if (stack_empty(btr
->stack
)) {
834 /* Root is a basic type */
835 btr
->state
= BTR_STATE_DONE
;
837 /* Go to next field */
838 stack_top(btr
->stack
)->index
++;
839 btr
->state
= BTR_STATE_NEXT_FIELD
;
840 btr
->last_bo
= btr
->cur_bo
;
845 /* We are here; it means we don't have enough data to decode this */
846 BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer.");
847 stitch_append_from_remaining_buf(btr
);
848 status
= BT_BTR_STATUS_EOF
;
855 enum bt_btr_status
read_basic_type_and_call_begin(struct bt_btr
*btr
,
856 read_basic_and_call_cb_t read_basic_and_call_cb
)
860 enum bt_byte_order bo
;
861 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
863 if (!at_least_one_bit_left(btr
)) {
864 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
865 status
= BT_BTR_STATUS_EOF
;
869 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
870 if (field_size
< 1) {
871 BT_LOGW("Cannot get basic field type's size: "
872 "btr-addr=%p, ft-addr=%p",
873 btr
, btr
->cur_basic_field_type
);
874 status
= BT_BTR_STATUS_ERROR
;
878 bo
= bt_field_type_get_byte_order(btr
->cur_basic_field_type
);
879 status
= validate_contiguous_bo(btr
, bo
);
880 if (status
!= BT_BTR_STATUS_OK
) {
881 /* validate_contiguous_bo() logs errors */
885 available
= available_bits(btr
);
887 if (field_size
<= available
) {
888 /* We have all the bits; decode and set now */
889 BT_ASSERT(btr
->buf
.addr
);
890 status
= read_basic_and_call_cb(btr
, btr
->buf
.addr
,
891 buf_at_from_addr(btr
));
892 if (status
!= BT_BTR_STATUS_OK
) {
893 BT_LOGW("Cannot read basic field: "
894 "btr-addr=%p, ft-addr=%p, status=%s",
895 btr
, btr
->cur_basic_field_type
,
896 bt_btr_status_string(status
));
900 consume_bits(btr
, field_size
);
902 if (stack_empty(btr
->stack
)) {
903 /* Root is a basic type */
904 btr
->state
= BTR_STATE_DONE
;
906 /* Go to next field */
907 stack_top(btr
->stack
)->index
++;
908 btr
->state
= BTR_STATE_NEXT_FIELD
;
909 btr
->last_bo
= btr
->cur_bo
;
915 /* We are here; it means we don't have enough data to decode this */
916 BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer.");
917 stitch_set_from_remaining_buf(btr
);
918 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
919 status
= BT_BTR_STATUS_EOF
;
926 enum bt_btr_status
read_basic_int_type_and_call_begin(
929 return read_basic_type_and_call_begin(btr
, read_basic_int_and_call_cb
);
933 enum bt_btr_status
read_basic_int_type_and_call_continue(
936 return read_basic_type_and_call_continue(btr
,
937 read_basic_int_and_call_cb
);
941 enum bt_btr_status
read_basic_float_type_and_call_begin(
944 return read_basic_type_and_call_begin(btr
,
945 read_basic_float_and_call_cb
);
949 enum bt_btr_status
read_basic_float_type_and_call_continue(
952 return read_basic_type_and_call_continue(btr
,
953 read_basic_float_and_call_cb
);
957 enum bt_btr_status
read_basic_enum_type_and_call_begin(
960 return read_basic_type_and_call_begin(btr
,
961 read_basic_enum_and_call_cb
);
965 enum bt_btr_status
read_basic_enum_type_and_call_continue(
968 return read_basic_type_and_call_continue(btr
,
969 read_basic_enum_and_call_cb
);
973 enum bt_btr_status
read_basic_string_type_and_call(
974 struct bt_btr
*btr
, bool begin
)
977 const uint8_t *result
;
978 size_t available_bytes
;
979 const uint8_t *first_chr
;
980 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
982 if (!at_least_one_bit_left(btr
)) {
983 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
984 status
= BT_BTR_STATUS_EOF
;
988 BT_ASSERT(buf_at_from_addr(btr
) % 8 == 0);
989 available_bytes
= BITS_TO_BYTES_FLOOR(available_bits(btr
));
990 buf_at_bytes
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr
));
991 BT_ASSERT(btr
->buf
.addr
);
992 first_chr
= &btr
->buf
.addr
[buf_at_bytes
];
993 result
= memchr(first_chr
, '\0', available_bytes
);
995 if (begin
&& btr
->user
.cbs
.types
.string_begin
) {
996 BT_LOGV("Calling user function (string, beginning).");
997 status
= btr
->user
.cbs
.types
.string_begin(
998 btr
->cur_basic_field_type
, btr
->user
.data
);
999 BT_LOGV("User function returned: status=%s",
1000 bt_btr_status_string(status
));
1001 if (status
!= BT_BTR_STATUS_OK
) {
1002 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1003 btr
, bt_btr_status_string(status
));
1009 /* No null character yet */
1010 if (btr
->user
.cbs
.types
.string
) {
1011 BT_LOGV("Calling user function (substring).");
1012 status
= btr
->user
.cbs
.types
.string(
1013 (const char *) first_chr
,
1014 available_bytes
, btr
->cur_basic_field_type
,
1016 BT_LOGV("User function returned: status=%s",
1017 bt_btr_status_string(status
));
1018 if (status
!= BT_BTR_STATUS_OK
) {
1019 BT_LOGW("User function failed: "
1020 "btr-addr=%p, status=%s",
1021 btr
, bt_btr_status_string(status
));
1026 consume_bits(btr
, BYTES_TO_BITS(available_bytes
));
1027 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
1028 status
= BT_BTR_STATUS_EOF
;
1030 /* Found the null character */
1031 size_t result_len
= (size_t) (result
- first_chr
);
1033 if (btr
->user
.cbs
.types
.string
&& result_len
) {
1034 BT_LOGV("Calling user function (substring).");
1035 status
= btr
->user
.cbs
.types
.string(
1036 (const char *) first_chr
,
1037 result_len
, btr
->cur_basic_field_type
,
1039 BT_LOGV("User function returned: status=%s",
1040 bt_btr_status_string(status
));
1041 if (status
!= BT_BTR_STATUS_OK
) {
1042 BT_LOGW("User function failed: "
1043 "btr-addr=%p, status=%s",
1044 btr
, bt_btr_status_string(status
));
1049 if (btr
->user
.cbs
.types
.string_end
) {
1050 BT_LOGV("Calling user function (string, end).");
1051 status
= btr
->user
.cbs
.types
.string_end(
1052 btr
->cur_basic_field_type
, btr
->user
.data
);
1053 BT_LOGV("User function returned: status=%s",
1054 bt_btr_status_string(status
));
1055 if (status
!= BT_BTR_STATUS_OK
) {
1056 BT_LOGW("User function failed: "
1057 "btr-addr=%p, status=%s",
1058 btr
, bt_btr_status_string(status
));
1063 consume_bits(btr
, BYTES_TO_BITS(result_len
+ 1));
1065 if (stack_empty(btr
->stack
)) {
1066 /* Root is a basic type */
1067 btr
->state
= BTR_STATE_DONE
;
1069 /* Go to next field */
1070 stack_top(btr
->stack
)->index
++;
1071 btr
->state
= BTR_STATE_NEXT_FIELD
;
1072 btr
->last_bo
= btr
->cur_bo
;
1081 enum bt_btr_status
read_basic_begin_state(struct bt_btr
*btr
)
1083 enum bt_btr_status status
;
1085 BT_ASSERT(btr
->cur_basic_field_type
);
1087 switch (bt_field_type_get_type_id(btr
->cur_basic_field_type
)) {
1088 case BT_FIELD_TYPE_ID_INTEGER
:
1089 status
= read_basic_int_type_and_call_begin(btr
);
1091 case BT_FIELD_TYPE_ID_FLOAT
:
1092 status
= read_basic_float_type_and_call_begin(btr
);
1094 case BT_FIELD_TYPE_ID_ENUM
:
1095 status
= read_basic_enum_type_and_call_begin(btr
);
1097 case BT_FIELD_TYPE_ID_STRING
:
1098 status
= read_basic_string_type_and_call(btr
, true);
1101 BT_LOGF("Unknown basic field type ID: "
1102 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1103 btr
, btr
->cur_basic_field_type
,
1104 bt_common_field_type_id_string(
1105 bt_field_type_get_type_id(
1106 btr
->cur_basic_field_type
)));
1114 enum bt_btr_status
read_basic_continue_state(struct bt_btr
*btr
)
1116 enum bt_btr_status status
;
1118 BT_ASSERT(btr
->cur_basic_field_type
);
1120 switch (bt_field_type_get_type_id(btr
->cur_basic_field_type
)) {
1121 case BT_FIELD_TYPE_ID_INTEGER
:
1122 status
= read_basic_int_type_and_call_continue(btr
);
1124 case BT_FIELD_TYPE_ID_FLOAT
:
1125 status
= read_basic_float_type_and_call_continue(btr
);
1127 case BT_FIELD_TYPE_ID_ENUM
:
1128 status
= read_basic_enum_type_and_call_continue(btr
);
1130 case BT_FIELD_TYPE_ID_STRING
:
1131 status
= read_basic_string_type_and_call(btr
, false);
1134 BT_LOGF("Unknown basic field type ID: "
1135 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1136 btr
, btr
->cur_basic_field_type
,
1137 bt_common_field_type_id_string(
1138 bt_field_type_get_type_id(
1139 btr
->cur_basic_field_type
)));
1147 size_t bits_to_skip_to_align_to(struct bt_btr
*btr
, size_t align
)
1149 size_t aligned_packet_at
;
1151 aligned_packet_at
= ALIGN(packet_at(btr
), align
);
1152 return aligned_packet_at
- packet_at(btr
);
1156 enum bt_btr_status
align_type_state(struct bt_btr
*btr
,
1157 struct bt_field_type
*field_type
, enum btr_state next_state
)
1159 int field_alignment
;
1161 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1163 /* Get field's alignment */
1164 field_alignment
= bt_field_type_get_alignment(field_type
);
1165 if (field_alignment
< 0) {
1166 BT_LOGW("Cannot get field type's alignment: "
1167 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1169 bt_common_field_type_id_string(
1170 bt_field_type_get_type_id(field_type
)));
1171 status
= BT_BTR_STATUS_ERROR
;
1176 * 0 means "undefined" for variants; what we really want is 1
1179 if (field_alignment
== 0) {
1180 field_alignment
= 1;
1183 /* Compute how many bits we need to skip */
1184 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1186 /* Nothing to skip? aligned */
1187 if (skip_bits
== 0) {
1188 btr
->state
= next_state
;
1192 /* Make sure there's at least one bit left */
1193 if (!at_least_one_bit_left(btr
)) {
1194 status
= BT_BTR_STATUS_EOF
;
1198 /* Consume as many bits as possible in what's left */
1199 consume_bits(btr
, MIN(available_bits(btr
), skip_bits
));
1201 /* Are we done now? */
1202 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1203 if (skip_bits
== 0) {
1204 /* Yes: go to next state */
1205 btr
->state
= next_state
;
1208 /* No: need more data */
1209 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr
);
1210 status
= BT_BTR_STATUS_EOF
;
1218 bool is_compound_type(struct bt_field_type
*field_type
)
1220 enum bt_field_type_id id
= bt_field_type_get_type_id(field_type
);
1222 return id
== BT_FIELD_TYPE_ID_STRUCT
|| id
== BT_FIELD_TYPE_ID_ARRAY
||
1223 id
== BT_FIELD_TYPE_ID_SEQUENCE
|| id
== BT_FIELD_TYPE_ID_VARIANT
;
1227 enum bt_btr_status
next_field_state(struct bt_btr
*btr
)
1230 struct stack_entry
*top
;
1231 struct bt_field_type
*next_field_type
= NULL
;
1232 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1234 if (stack_empty(btr
->stack
)) {
1238 top
= stack_top(btr
->stack
);
1240 /* Are we done with this base type? */
1241 while (top
->index
== top
->base_len
) {
1242 if (btr
->user
.cbs
.types
.compound_end
) {
1243 BT_LOGV("Calling user function (compound, end).");
1244 status
= btr
->user
.cbs
.types
.compound_end(
1245 top
->base_type
, btr
->user
.data
);
1246 BT_LOGV("User function returned: status=%s",
1247 bt_btr_status_string(status
));
1248 if (status
!= BT_BTR_STATUS_OK
) {
1249 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1250 btr
, bt_btr_status_string(status
));
1255 stack_pop(btr
->stack
);
1257 /* Are we done with the root type? */
1258 if (stack_empty(btr
->stack
)) {
1259 btr
->state
= BTR_STATE_DONE
;
1263 top
= stack_top(btr
->stack
);
1267 /* Get next field's type */
1268 switch (bt_field_type_get_type_id(top
->base_type
)) {
1269 case BT_FIELD_TYPE_ID_STRUCT
:
1270 ret
= bt_field_type_structure_borrow_field_by_index(
1271 top
->base_type
, NULL
, &next_field_type
,
1274 next_field_type
= NULL
;
1277 case BT_FIELD_TYPE_ID_ARRAY
:
1279 bt_field_type_array_borrow_element_field_type(
1282 case BT_FIELD_TYPE_ID_SEQUENCE
:
1284 bt_field_type_sequence_borrow_element_field_type(
1287 case BT_FIELD_TYPE_ID_VARIANT
:
1288 /* Variant types are dynamic: query the user, he should know! */
1290 btr
->user
.cbs
.query
.borrow_variant_field_type(
1291 top
->base_type
, btr
->user
.data
);
1297 if (!next_field_type
) {
1298 BT_LOGW("Cannot get the field type of the next field: "
1299 "btr-addr=%p, base-ft-addr=%p, base-ft-id=%s, "
1301 btr
, top
->base_type
,
1302 bt_common_field_type_id_string(
1303 bt_field_type_get_type_id(top
->base_type
)),
1305 status
= BT_BTR_STATUS_ERROR
;
1309 if (is_compound_type(next_field_type
)) {
1310 if (btr
->user
.cbs
.types
.compound_begin
) {
1311 BT_LOGV("Calling user function (compound, begin).");
1312 status
= btr
->user
.cbs
.types
.compound_begin(
1313 next_field_type
, btr
->user
.data
);
1314 BT_LOGV("User function returned: status=%s",
1315 bt_btr_status_string(status
));
1316 if (status
!= BT_BTR_STATUS_OK
) {
1317 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1318 btr
, bt_btr_status_string(status
));
1323 ret
= stack_push_with_len(btr
, next_field_type
);
1325 /* stack_push_with_len() logs errors */
1326 status
= BT_BTR_STATUS_ERROR
;
1330 /* Next state: align a compound type */
1331 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
1333 /* Replace current basic field type */
1334 BT_LOGV("Replacing current basic field type: "
1335 "btr-addr=%p, cur-basic-ft-addr=%p, "
1336 "next-basic-ft-addr=%p",
1337 btr
, btr
->cur_basic_field_type
, next_field_type
);
1338 btr
->cur_basic_field_type
= next_field_type
;
1340 /* Next state: align a basic type */
1341 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1349 enum bt_btr_status
handle_state(struct bt_btr
*btr
)
1351 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1353 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1354 btr
, btr_state_string(btr
->state
));
1356 switch (btr
->state
) {
1357 case BTR_STATE_NEXT_FIELD
:
1358 status
= next_field_state(btr
);
1360 case BTR_STATE_ALIGN_BASIC
:
1361 status
= align_type_state(btr
, btr
->cur_basic_field_type
,
1362 BTR_STATE_READ_BASIC_BEGIN
);
1364 case BTR_STATE_ALIGN_COMPOUND
:
1365 status
= align_type_state(btr
, stack_top(btr
->stack
)->base_type
,
1366 BTR_STATE_NEXT_FIELD
);
1368 case BTR_STATE_READ_BASIC_BEGIN
:
1369 status
= read_basic_begin_state(btr
);
1371 case BTR_STATE_READ_BASIC_CONTINUE
:
1372 status
= read_basic_continue_state(btr
);
1374 case BTR_STATE_DONE
:
1378 BT_LOGV("Handled state: btr-addr=%p, status=%s",
1379 btr
, bt_btr_status_string(status
));
1383 struct bt_btr
*bt_btr_create(struct bt_btr_cbs cbs
, void *data
)
1387 BT_LOGD_STR("Creating binary type reader (BTR).");
1388 btr
= g_new0(struct bt_btr
, 1);
1390 BT_LOGE_STR("Failed to allocate one binary type reader.");
1394 btr
->stack
= stack_new();
1396 BT_LOGE_STR("Cannot create BTR's stack.");
1397 bt_btr_destroy(btr
);
1402 btr
->state
= BTR_STATE_NEXT_FIELD
;
1403 btr
->user
.cbs
= cbs
;
1404 btr
->user
.data
= data
;
1405 BT_LOGD("Created BTR: addr=%p", btr
);
1411 void bt_btr_destroy(struct bt_btr
*btr
)
1414 stack_destroy(btr
->stack
);
1417 BT_LOGD("Destroying BTR: addr=%p", btr
);
1422 void reset(struct bt_btr
*btr
)
1424 BT_LOGD("Resetting BTR: addr=%p", btr
);
1425 stack_clear(btr
->stack
);
1427 btr
->buf
.addr
= NULL
;
1428 btr
->last_bo
= BT_BYTE_ORDER_UNKNOWN
;
1432 void update_packet_offset(struct bt_btr
*btr
)
1434 BT_LOGV("Updating packet offset for next call: "
1435 "btr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1436 btr
, btr
->buf
.packet_offset
,
1437 btr
->buf
.packet_offset
+ btr
->buf
.at
);
1438 btr
->buf
.packet_offset
+= btr
->buf
.at
;
1441 size_t bt_btr_start(struct bt_btr
*btr
,
1442 struct bt_field_type
*type
, const uint8_t *buf
,
1443 size_t offset
, size_t packet_offset
, size_t sz
,
1444 enum bt_btr_status
*status
)
1447 BT_ASSERT(BYTES_TO_BITS(sz
) >= offset
);
1449 btr
->buf
.addr
= buf
;
1450 btr
->buf
.offset
= offset
;
1452 btr
->buf
.packet_offset
= packet_offset
;
1453 btr
->buf
.buf_sz
= sz
;
1454 btr
->buf
.sz
= BYTES_TO_BITS(sz
) - offset
;
1455 *status
= BT_BTR_STATUS_OK
;
1457 BT_LOGV("Starting decoding: btr-addr=%p, ft-addr=%p, "
1458 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1459 "packet-offset=%zu",
1460 btr
, type
, buf
, sz
, offset
, packet_offset
);
1463 if (is_compound_type(type
)) {
1464 /* Compound type: push on visit stack */
1467 if (btr
->user
.cbs
.types
.compound_begin
) {
1468 BT_LOGV("Calling user function (compound, begin).");
1469 *status
= btr
->user
.cbs
.types
.compound_begin(
1470 type
, btr
->user
.data
);
1471 BT_LOGV("User function returned: status=%s",
1472 bt_btr_status_string(*status
));
1473 if (*status
!= BT_BTR_STATUS_OK
) {
1474 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1475 btr
, bt_btr_status_string(*status
));
1480 stack_ret
= stack_push_with_len(btr
, type
);
1482 /* stack_push_with_len() logs errors */
1483 *status
= BT_BTR_STATUS_ERROR
;
1487 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
1489 /* Basic type: set as current basic type */
1490 btr
->cur_basic_field_type
= type
;
1491 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1494 /* Run the machine! */
1495 BT_LOGV_STR("Running the state machine.");
1498 *status
= handle_state(btr
);
1499 if (*status
!= BT_BTR_STATUS_OK
||
1500 btr
->state
== BTR_STATE_DONE
) {
1505 /* Update packet offset for next time */
1506 update_packet_offset(btr
);
1512 size_t bt_btr_continue(struct bt_btr
*btr
,
1513 const uint8_t *buf
, size_t sz
,
1514 enum bt_btr_status
*status
)
1519 btr
->buf
.addr
= buf
;
1520 btr
->buf
.offset
= 0;
1522 btr
->buf
.buf_sz
= sz
;
1523 btr
->buf
.sz
= BYTES_TO_BITS(sz
);
1524 *status
= BT_BTR_STATUS_OK
;
1526 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1529 /* Continue running the machine */
1530 BT_LOGV_STR("Running the state machine.");
1533 *status
= handle_state(btr
);
1534 if (*status
!= BT_BTR_STATUS_OK
||
1535 btr
->state
== BTR_STATE_DONE
) {
1540 /* Update packet offset for next time */
1541 update_packet_offset(btr
);