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"
37 #include <babeltrace/bitfield-internal.h>
38 #include <babeltrace/babeltrace.h>
39 #include <babeltrace/ctf-ir/field-types-internal.h>
40 #include <babeltrace/ref.h>
41 #include <babeltrace/align-internal.h>
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
;
184 BT_PUT(entry
->base_type
);
189 struct stack
*stack_new(void)
191 struct stack
*stack
= NULL
;
193 stack
= g_new0(struct stack
, 1);
195 BT_LOGE_STR("Failed to allocate one stack.");
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.");
205 BT_LOGD("Created stack: addr=%p", stack
);
215 void stack_destroy(struct stack
*stack
)
221 BT_LOGD("Destroying stack: addr=%p", stack
);
222 g_ptr_array_free(stack
->entries
, TRUE
);
227 int64_t get_compound_field_type_length(struct bt_btr
*btr
,
228 struct bt_field_type
*field_type
)
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(
237 case BT_FIELD_TYPE_ID_VARIANT
:
238 /* Variant field types always "contain" a single type */
241 case BT_FIELD_TYPE_ID_ARRAY
:
242 length
= bt_field_type_array_get_length(field_type
);
244 case BT_FIELD_TYPE_ID_SEQUENCE
:
245 length
= btr
->user
.cbs
.query
.get_sequence_length(field_type
,
249 BT_LOGW("Cannot get field type's field count: btr-addr=%p, "
250 "ft-addr=%p, ft-id=%s",
252 bt_field_type_id_string(
253 bt_field_type_get_type_id(field_type
)));
254 length
= BT_BTR_STATUS_ERROR
;
261 int stack_push(struct stack
*stack
, struct bt_field_type
*base_type
,
265 struct stack_entry
*entry
;
270 BT_LOGV("Pushing field type on stack: stack-addr=%p, "
271 "ft-addr=%p, ft-id=%s, base-length=%zu, "
272 "stack-size-before=%u, stack-size-after=%u",
273 stack
, base_type
, bt_field_type_id_string(
274 bt_field_type_get_type_id(base_type
)),
275 base_len
, stack
->entries
->len
, stack
->entries
->len
+ 1);
276 entry
= g_new0(struct stack_entry
, 1);
278 BT_LOGE("Failed to allocate one stack entry: stack-addr=%p",
280 ret
= BT_BTR_STATUS_ERROR
;
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
);
294 int stack_push_with_len(struct bt_btr
*btr
,
295 struct bt_field_type
*base_type
)
298 int64_t base_len
= get_compound_field_type_length(btr
, base_type
);
301 BT_LOGW("Cannot get compound field type's field count: "
302 "btr-addr=%p, ft-addr=%p, ft-id=%s",
303 btr
, base_type
, bt_field_type_id_string(
304 bt_field_type_get_type_id(base_type
)));
305 ret
= BT_BTR_STATUS_ERROR
;
309 ret
= stack_push(btr
->stack
, base_type
, (size_t) base_len
);
316 unsigned int stack_size(struct stack
*stack
)
320 return stack
->entries
->len
;
324 void stack_pop(struct stack
*stack
)
327 assert(stack_size(stack
));
328 BT_LOGV("Popping from stack: "
329 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
330 stack
, stack
->entries
->len
, stack
->entries
->len
- 1);
331 g_ptr_array_remove_index(stack
->entries
, stack
->entries
->len
- 1);
335 bool stack_empty(struct stack
*stack
)
337 return stack_size(stack
) == 0;
341 void stack_clear(struct stack
*stack
)
345 if (!stack_empty(stack
)) {
346 g_ptr_array_remove_range(stack
->entries
, 0, stack_size(stack
));
349 assert(stack_empty(stack
));
353 struct stack_entry
*stack_top(struct stack
*stack
)
356 assert(stack_size(stack
));
358 return g_ptr_array_index(stack
->entries
, stack
->entries
->len
- 1);
362 size_t available_bits(struct bt_btr
*btr
)
364 return btr
->buf
.sz
- btr
->buf
.at
;
368 void consume_bits(struct bt_btr
*btr
, size_t incr
)
370 BT_LOGV("Advancing cursor: btr-addr=%p, cur-before=%zu, cur-after=%zu",
371 btr
, btr
->buf
.at
, btr
->buf
.at
+ incr
);
376 bool has_enough_bits(struct bt_btr
*btr
, size_t sz
)
378 return available_bits(btr
) >= sz
;
382 bool at_least_one_bit_left(struct bt_btr
*btr
)
384 return has_enough_bits(btr
, 1);
388 size_t packet_at(struct bt_btr
*btr
)
390 return btr
->buf
.packet_offset
+ btr
->buf
.at
;
394 size_t buf_at_from_addr(struct bt_btr
*btr
)
399 * ====== offset ===== (17)
401 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
403 * addr (0) ==== at ==== (12)
407 * =============================== (29)
409 return btr
->buf
.offset
+ btr
->buf
.at
;
413 int get_basic_field_type_size(struct bt_btr
*btr
,
414 struct bt_field_type
*field_type
)
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
);
422 case BT_FIELD_TYPE_ID_FLOAT
:
424 int exp_dig
, mant_dig
;
427 bt_field_type_floating_point_get_exponent_digits(
430 bt_field_type_floating_point_get_mantissa_digits(
432 assert(exp_dig
>= 0);
433 assert(mant_dig
>= 0);
434 size
= exp_dig
+ mant_dig
;
437 case BT_FIELD_TYPE_ID_ENUM
:
439 struct bt_field_type
*int_type
;
441 int_type
= bt_field_type_enumeration_get_container_type(
444 size
= get_basic_field_type_size(btr
, int_type
);
449 size
= BT_BTR_STATUS_ERROR
;
457 void stitch_reset(struct bt_btr
*btr
)
459 btr
->stitch
.offset
= 0;
464 size_t stitch_at_from_addr(struct bt_btr
*btr
)
466 return btr
->stitch
.offset
+ btr
->stitch
.at
;
470 void stitch_append_from_buf(struct bt_btr
*btr
, size_t sz
)
472 size_t stitch_byte_at
;
481 BITS_TO_BYTES_FLOOR(stitch_at_from_addr(btr
));
482 buf_byte_at
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr
));
483 nb_bytes
= BITS_TO_BYTES_CEIL(sz
);
484 assert(nb_bytes
> 0);
485 assert(btr
->buf
.addr
);
486 memcpy(&btr
->stitch
.buf
[stitch_byte_at
], &btr
->buf
.addr
[buf_byte_at
],
488 btr
->stitch
.at
+= sz
;
489 consume_bits(btr
, sz
);
493 void stitch_append_from_remaining_buf(struct bt_btr
*btr
)
495 stitch_append_from_buf(btr
, available_bits(btr
));
499 void stitch_set_from_remaining_buf(struct bt_btr
*btr
)
502 btr
->stitch
.offset
= IN_BYTE_OFFSET(buf_at_from_addr(btr
));
503 stitch_append_from_remaining_buf(btr
);
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
)
510 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
);
517 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
518 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
521 BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo
);
525 BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64
", "
526 "bo=%s, val=%" PRIu64
, at
, field_size
,
527 bt_byte_order_string(bo
), *v
);
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
)
535 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
);
542 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
543 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
546 BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo
);
550 BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64
", "
551 "bo=%s, val=%" PRId64
, at
, field_size
,
552 bt_byte_order_string(bo
), *v
);
556 typedef enum bt_btr_status (* read_basic_and_call_cb_t
)(struct bt_btr
*,
557 const uint8_t *, size_t);
560 enum bt_btr_status
validate_contiguous_bo(struct bt_btr
*btr
,
561 enum bt_byte_order next_bo
)
563 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
565 /* Always valid when at a byte boundary */
566 if (packet_at(btr
) % 8 == 0) {
570 /* Always valid if last byte order is unknown */
571 if (btr
->last_bo
== BT_BYTE_ORDER_UNKNOWN
) {
575 /* Always valid if next byte order is unknown */
576 if (next_bo
== BT_BYTE_ORDER_UNKNOWN
) {
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
;
589 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
590 if (next_bo
!= BT_BYTE_ORDER_LITTLE_ENDIAN
) {
591 status
= BT_BTR_STATUS_ERROR
;
595 status
= BT_BTR_STATUS_ERROR
;
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_byte_order_string(btr
->last_bo
),
603 bt_byte_order_string(next_bo
));
610 enum bt_btr_status
read_basic_float_and_call_cb(struct bt_btr
*btr
,
611 const uint8_t *buf
, size_t at
)
616 enum bt_byte_order bo
;
617 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
);
623 switch (field_size
) {
632 ret
= bt_field_type_floating_point_get_mantissa_digits(
633 btr
->cur_basic_field_type
);
635 ret
= bt_field_type_floating_point_get_exponent_digits(
636 btr
->cur_basic_field_type
);
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
));
646 f32
.u
= (uint32_t) v
;
647 dblval
= (double) f32
.f
;
657 ret
= bt_field_type_floating_point_get_mantissa_digits(
658 btr
->cur_basic_field_type
);
660 ret
= bt_field_type_floating_point_get_exponent_digits(
661 btr
->cur_basic_field_type
);
663 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
,
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
));
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: "
679 status
= BT_BTR_STATUS_ERROR
;
683 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
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
));
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
)
710 enum bt_byte_order bo
;
711 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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",
719 status
= BT_BTR_STATUS_ERROR
;
723 bo
= bt_field_type_get_byte_order(int_type
);
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.
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
));
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
));
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
));
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
));
785 enum bt_btr_status
read_basic_int_and_call_cb(struct bt_btr
*btr
,
786 const uint8_t *buf
, size_t at
)
788 return read_basic_int_and_call(btr
, buf
, at
, btr
->cur_basic_field_type
,
789 btr
->cur_basic_field_type
);
793 enum bt_btr_status
read_basic_enum_and_call_cb(struct bt_btr
*btr
,
794 const uint8_t *buf
, size_t at
)
796 struct bt_field_type
*int_field_type
;
797 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
799 int_field_type
= bt_field_type_enumeration_get_container_type(
800 btr
->cur_basic_field_type
);
801 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
);
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
)
815 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
;
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
;
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
,
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
));
851 if (stack_empty(btr
->stack
)) {
852 /* Root is a basic type */
853 btr
->state
= BTR_STATE_DONE
;
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
;
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
;
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
)
878 enum bt_byte_order bo
;
879 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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
;
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
;
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 */
903 available
= available_bits(btr
);
905 if (field_size
<= available
) {
906 /* We have all the bits; decode and set now */
907 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
));
918 consume_bits(btr
, field_size
);
920 if (stack_empty(btr
->stack
)) {
921 /* Root is a basic type */
922 btr
->state
= BTR_STATE_DONE
;
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
;
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
;
944 enum bt_btr_status
read_basic_int_type_and_call_begin(
947 return read_basic_type_and_call_begin(btr
, read_basic_int_and_call_cb
);
951 enum bt_btr_status
read_basic_int_type_and_call_continue(
954 return read_basic_type_and_call_continue(btr
,
955 read_basic_int_and_call_cb
);
959 enum bt_btr_status
read_basic_float_type_and_call_begin(
962 return read_basic_type_and_call_begin(btr
,
963 read_basic_float_and_call_cb
);
967 enum bt_btr_status
read_basic_float_type_and_call_continue(
970 return read_basic_type_and_call_continue(btr
,
971 read_basic_float_and_call_cb
);
975 enum bt_btr_status
read_basic_enum_type_and_call_begin(
978 return read_basic_type_and_call_begin(btr
,
979 read_basic_enum_and_call_cb
);
983 enum bt_btr_status
read_basic_enum_type_and_call_continue(
986 return read_basic_type_and_call_continue(btr
,
987 read_basic_enum_and_call_cb
);
991 enum bt_btr_status
read_basic_string_type_and_call(
992 struct bt_btr
*btr
, bool begin
)
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
;
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
;
1006 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 assert(btr
->buf
.addr
);
1010 first_chr
= &btr
->buf
.addr
[buf_at_bytes
];
1011 result
= memchr(first_chr
, '\0', available_bytes
);
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
));
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
,
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
));
1044 consume_bits(btr
, BYTES_TO_BITS(available_bytes
));
1045 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
1046 status
= BT_BTR_STATUS_EOF
;
1048 /* Found the null character */
1049 size_t result_len
= (size_t) (result
- first_chr
);
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
,
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
));
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
));
1081 consume_bits(btr
, BYTES_TO_BITS(result_len
+ 1));
1083 if (stack_empty(btr
->stack
)) {
1084 /* Root is a basic type */
1085 btr
->state
= BTR_STATE_DONE
;
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
;
1099 enum bt_btr_status
read_basic_begin_state(struct bt_btr
*btr
)
1101 enum bt_btr_status status
;
1103 assert(btr
->cur_basic_field_type
);
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
);
1109 case BT_FIELD_TYPE_ID_FLOAT
:
1110 status
= read_basic_float_type_and_call_begin(btr
);
1112 case BT_FIELD_TYPE_ID_ENUM
:
1113 status
= read_basic_enum_type_and_call_begin(btr
);
1115 case BT_FIELD_TYPE_ID_STRING
:
1116 status
= read_basic_string_type_and_call(btr
, true);
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_field_type_id_string(
1123 bt_field_type_get_type_id(
1124 btr
->cur_basic_field_type
)));
1132 enum bt_btr_status
read_basic_continue_state(struct bt_btr
*btr
)
1134 enum bt_btr_status status
;
1136 assert(btr
->cur_basic_field_type
);
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
);
1142 case BT_FIELD_TYPE_ID_FLOAT
:
1143 status
= read_basic_float_type_and_call_continue(btr
);
1145 case BT_FIELD_TYPE_ID_ENUM
:
1146 status
= read_basic_enum_type_and_call_continue(btr
);
1148 case BT_FIELD_TYPE_ID_STRING
:
1149 status
= read_basic_string_type_and_call(btr
, false);
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_field_type_id_string(
1156 bt_field_type_get_type_id(
1157 btr
->cur_basic_field_type
)));
1165 size_t bits_to_skip_to_align_to(struct bt_btr
*btr
, size_t align
)
1167 size_t aligned_packet_at
;
1169 aligned_packet_at
= ALIGN(packet_at(btr
), align
);
1170 return aligned_packet_at
- packet_at(btr
);
1174 enum bt_btr_status
align_type_state(struct bt_btr
*btr
,
1175 struct bt_field_type
*field_type
, enum btr_state next_state
)
1177 int field_alignment
;
1179 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
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",
1187 bt_field_type_id_string(
1188 bt_field_type_get_type_id(field_type
)));
1189 status
= BT_BTR_STATUS_ERROR
;
1194 * 0 means "undefined" for variants; what we really want is 1
1197 if (field_alignment
== 0) {
1198 field_alignment
= 1;
1201 /* Compute how many bits we need to skip */
1202 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1204 /* Nothing to skip? aligned */
1205 if (skip_bits
== 0) {
1206 btr
->state
= next_state
;
1210 /* Make sure there's at least one bit left */
1211 if (!at_least_one_bit_left(btr
)) {
1212 status
= BT_BTR_STATUS_EOF
;
1216 /* Consume as many bits as possible in what's left */
1217 consume_bits(btr
, MIN(available_bits(btr
), skip_bits
));
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
;
1226 /* No: need more data */
1227 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr
);
1228 status
= BT_BTR_STATUS_EOF
;
1236 bool is_compound_type(struct bt_field_type
*field_type
)
1238 enum bt_field_type_id id
= bt_field_type_get_type_id(field_type
);
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
;
1245 enum bt_btr_status
next_field_state(struct bt_btr
*btr
)
1248 struct stack_entry
*top
;
1249 struct bt_field_type
*next_field_type
= NULL
;
1250 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1252 if (stack_empty(btr
->stack
)) {
1256 top
= stack_top(btr
->stack
);
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
));
1273 stack_pop(btr
->stack
);
1275 /* Are we done with the root type? */
1276 if (stack_empty(btr
->stack
)) {
1277 btr
->state
= BTR_STATE_DONE
;
1281 top
= stack_top(btr
->stack
);
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
,
1292 next_field_type
= NULL
;
1295 case BT_FIELD_TYPE_ID_ARRAY
:
1297 bt_field_type_array_get_element_type(
1300 case BT_FIELD_TYPE_ID_SEQUENCE
:
1302 bt_field_type_sequence_get_element_type(
1305 case BT_FIELD_TYPE_ID_VARIANT
:
1306 /* Variant types are dynamic: query the user, he should know! */
1308 btr
->user
.cbs
.query
.get_variant_type(
1309 top
->base_type
, btr
->user
.data
);
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, "
1319 btr
, top
->base_type
,
1320 bt_field_type_id_string(
1321 bt_field_type_get_type_id(top
->base_type
)),
1323 status
= BT_BTR_STATUS_ERROR
;
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
));
1341 ret
= stack_push_with_len(btr
, next_field_type
);
1343 /* stack_push_with_len() logs errors */
1344 status
= BT_BTR_STATUS_ERROR
;
1348 /* Next state: align a compound type */
1349 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
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
);
1358 /* Next state: align a basic type */
1359 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1363 BT_PUT(next_field_type
);
1369 enum bt_btr_status
handle_state(struct bt_btr
*btr
)
1371 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1373 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1374 btr
, btr_state_string(btr
->state
));
1376 switch (btr
->state
) {
1377 case BTR_STATE_NEXT_FIELD
:
1378 status
= next_field_state(btr
);
1380 case BTR_STATE_ALIGN_BASIC
:
1381 status
= align_type_state(btr
, btr
->cur_basic_field_type
,
1382 BTR_STATE_READ_BASIC_BEGIN
);
1384 case BTR_STATE_ALIGN_COMPOUND
:
1385 status
= align_type_state(btr
, stack_top(btr
->stack
)->base_type
,
1386 BTR_STATE_NEXT_FIELD
);
1388 case BTR_STATE_READ_BASIC_BEGIN
:
1389 status
= read_basic_begin_state(btr
);
1391 case BTR_STATE_READ_BASIC_CONTINUE
:
1392 status
= read_basic_continue_state(btr
);
1394 case BTR_STATE_DONE
:
1398 BT_LOGV("Handled state: btr-addr=%p, status=%s",
1399 btr
, bt_btr_status_string(status
));
1403 struct bt_btr
*bt_btr_create(struct bt_btr_cbs cbs
, void *data
)
1407 BT_LOGD_STR("Creating binary type reader (BTR).");
1408 btr
= g_new0(struct bt_btr
, 1);
1410 BT_LOGE_STR("Failed to allocate one binary type reader.");
1414 btr
->stack
= stack_new();
1416 BT_LOGE_STR("Cannot create BTR's stack.");
1417 bt_btr_destroy(btr
);
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
);
1431 void bt_btr_destroy(struct bt_btr
*btr
)
1434 stack_destroy(btr
->stack
);
1437 BT_LOGD("Destroying BTR: addr=%p", btr
);
1438 BT_PUT(btr
->cur_basic_field_type
);
1443 void reset(struct bt_btr
*btr
)
1445 BT_LOGD("Resetting BTR: addr=%p", btr
);
1446 stack_clear(btr
->stack
);
1447 BT_PUT(btr
->cur_basic_field_type
);
1449 btr
->buf
.addr
= NULL
;
1450 btr
->last_bo
= BT_BYTE_ORDER_UNKNOWN
;
1454 void update_packet_offset(struct bt_btr
*btr
)
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
;
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
)
1469 assert(BYTES_TO_BITS(sz
) >= offset
);
1471 btr
->buf
.addr
= buf
;
1472 btr
->buf
.offset
= offset
;
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
;
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
);
1485 if (is_compound_type(type
)) {
1486 /* Compound type: push on visit stack */
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
));
1502 stack_ret
= stack_push_with_len(btr
, type
);
1504 /* stack_push_with_len() logs errors */
1505 *status
= BT_BTR_STATUS_ERROR
;
1509 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
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
;
1517 /* Run the machine! */
1518 BT_LOGV_STR("Running the state machine.");
1521 *status
= handle_state(btr
);
1522 if (*status
!= BT_BTR_STATUS_OK
||
1523 btr
->state
== BTR_STATE_DONE
) {
1528 /* Update packet offset for next time */
1529 update_packet_offset(btr
);
1535 size_t bt_btr_continue(struct bt_btr
*btr
,
1536 const uint8_t *buf
, size_t sz
,
1537 enum bt_btr_status
*status
)
1542 btr
->buf
.addr
= buf
;
1543 btr
->buf
.offset
= 0;
1545 btr
->buf
.buf_sz
= sz
;
1546 btr
->buf
.sz
= BYTES_TO_BITS(sz
);
1547 *status
= BT_BTR_STATUS_OK
;
1549 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1552 /* Continue running the machine */
1553 BT_LOGV_STR("Running the state machine.");
1556 *status
= handle_state(btr
);
1557 if (*status
!= BT_BTR_STATUS_OK
||
1558 btr
->state
== BTR_STATE_DONE
) {
1563 /* Update packet offset for next time */
1564 update_packet_offset(btr
);