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 memcpy(&btr
->stitch
.buf
[stitch_byte_at
], &btr
->buf
.addr
[buf_byte_at
],
487 btr
->stitch
.at
+= sz
;
488 consume_bits(btr
, sz
);
492 void stitch_append_from_remaining_buf(struct bt_btr
*btr
)
494 stitch_append_from_buf(btr
, available_bits(btr
));
498 void stitch_set_from_remaining_buf(struct bt_btr
*btr
)
501 btr
->stitch
.offset
= IN_BYTE_OFFSET(buf_at_from_addr(btr
));
502 stitch_append_from_remaining_buf(btr
);
506 enum bt_btr_status
read_unsigned_bitfield(const uint8_t *buf
, size_t at
,
507 int64_t field_size
, enum bt_byte_order bo
, uint64_t *v
)
509 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
512 case BT_BYTE_ORDER_BIG_ENDIAN
:
513 case BT_BYTE_ORDER_NETWORK
:
514 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
516 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
517 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
520 BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo
);
524 BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64
", "
525 "bo=%s, val=%" PRIu64
, at
, field_size
,
526 bt_byte_order_string(bo
), *v
);
531 enum bt_btr_status
read_signed_bitfield(const uint8_t *buf
, size_t at
,
532 int64_t field_size
, enum bt_byte_order bo
, int64_t *v
)
534 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
537 case BT_BYTE_ORDER_BIG_ENDIAN
:
538 case BT_BYTE_ORDER_NETWORK
:
539 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
541 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
542 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
545 BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo
);
549 BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64
", "
550 "bo=%s, val=%" PRId64
, at
, field_size
,
551 bt_byte_order_string(bo
), *v
);
555 typedef enum bt_btr_status (* read_basic_and_call_cb_t
)(struct bt_btr
*,
556 const uint8_t *, size_t);
559 enum bt_btr_status
validate_contiguous_bo(struct bt_btr
*btr
,
560 enum bt_byte_order next_bo
)
562 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
564 /* Always valid when at a byte boundary */
565 if (packet_at(btr
) % 8 == 0) {
569 /* Always valid if last byte order is unknown */
570 if (btr
->last_bo
== BT_BYTE_ORDER_UNKNOWN
) {
574 /* Always valid if next byte order is unknown */
575 if (next_bo
== BT_BYTE_ORDER_UNKNOWN
) {
579 /* Make sure last byte order is compatible with the next byte order */
580 switch (btr
->last_bo
) {
581 case BT_BYTE_ORDER_BIG_ENDIAN
:
582 case BT_BYTE_ORDER_NETWORK
:
583 if (next_bo
!= BT_BYTE_ORDER_BIG_ENDIAN
&&
584 next_bo
!= BT_BYTE_ORDER_NETWORK
) {
585 status
= BT_BTR_STATUS_ERROR
;
588 case BT_BYTE_ORDER_LITTLE_ENDIAN
:
589 if (next_bo
!= BT_BYTE_ORDER_LITTLE_ENDIAN
) {
590 status
= BT_BTR_STATUS_ERROR
;
594 status
= BT_BTR_STATUS_ERROR
;
599 BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
600 "btr-addr=%p, last-bo=%s, next-bo=%s",
601 btr
, bt_byte_order_string(btr
->last_bo
),
602 bt_byte_order_string(next_bo
));
609 enum bt_btr_status
read_basic_float_and_call_cb(struct bt_btr
*btr
,
610 const uint8_t *buf
, size_t at
)
615 enum bt_byte_order bo
;
616 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
618 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
619 bo
= bt_field_type_get_byte_order(btr
->cur_basic_field_type
);
622 switch (field_size
) {
631 ret
= bt_field_type_floating_point_get_mantissa_digits(
632 btr
->cur_basic_field_type
);
634 ret
= bt_field_type_floating_point_get_exponent_digits(
635 btr
->cur_basic_field_type
);
637 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
, &v
);
638 if (status
!= BT_BTR_STATUS_OK
) {
639 BT_LOGW("Cannot read unsigned 32-bit bit array for floating point number field: "
640 "btr-addr=%p, status=%s",
641 btr
, bt_btr_status_string(status
));
645 f32
.u
= (uint32_t) v
;
646 dblval
= (double) f32
.f
;
656 ret
= bt_field_type_floating_point_get_mantissa_digits(
657 btr
->cur_basic_field_type
);
659 ret
= bt_field_type_floating_point_get_exponent_digits(
660 btr
->cur_basic_field_type
);
662 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
,
664 if (status
!= BT_BTR_STATUS_OK
) {
665 BT_LOGW("Cannot read unsigned 64-bit bit array for floating point number field: "
666 "btr-addr=%p, status=%s",
667 btr
, bt_btr_status_string(status
));
675 /* Only 32-bit and 64-bit fields are supported currently */
676 BT_LOGW("Only 32-bit and 64-bit floating point number fields are supported: "
678 status
= BT_BTR_STATUS_ERROR
;
682 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
685 if (btr
->user
.cbs
.types
.floating_point
) {
686 BT_LOGV("Calling user function (floating point number).");
687 status
= btr
->user
.cbs
.types
.floating_point(dblval
,
688 btr
->cur_basic_field_type
, btr
->user
.data
);
689 BT_LOGV("User function returned: status=%s",
690 bt_btr_status_string(status
));
691 if (status
!= BT_BTR_STATUS_OK
) {
692 BT_LOGW("User function failed: btr-addr=%p, status=%s",
693 btr
, bt_btr_status_string(status
));
702 enum bt_btr_status
read_basic_int_and_call(struct bt_btr
*btr
,
703 const uint8_t *buf
, size_t at
,
704 struct bt_field_type
*int_type
,
705 struct bt_field_type
*orig_type
)
709 enum bt_byte_order bo
;
710 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
712 signd
= bt_field_type_integer_is_signed(int_type
);
713 field_size
= get_basic_field_type_size(btr
, int_type
);
714 if (field_size
< 1) {
715 BT_LOGW("Cannot get integer field type's size: "
716 "btr=%p, at=%zu, ft-addr=%p",
718 status
= BT_BTR_STATUS_ERROR
;
722 bo
= bt_field_type_get_byte_order(int_type
);
725 * Update current byte order now because we could be reading
726 * the integer value of an enumeration type, and thus we know
727 * here the actual supporting integer type's byte order.
734 status
= read_signed_bitfield(buf
, at
, field_size
, bo
, &v
);
735 if (status
!= BT_BTR_STATUS_OK
) {
736 BT_LOGW("Cannot read signed bit array for signed integer field: "
737 "btr-addr=%p, status=%s",
738 btr
, bt_btr_status_string(status
));
742 if (btr
->user
.cbs
.types
.signed_int
) {
743 BT_LOGV("Calling user function (signed integer).");
744 status
= btr
->user
.cbs
.types
.signed_int(v
,
745 btr
->cur_basic_field_type
, btr
->user
.data
);
746 BT_LOGV("User function returned: status=%s",
747 bt_btr_status_string(status
));
748 if (status
!= BT_BTR_STATUS_OK
) {
749 BT_LOGW("User function failed: "
750 "btr-addr=%p, status=%s",
751 btr
, bt_btr_status_string(status
));
757 status
= read_unsigned_bitfield(buf
, at
, field_size
, bo
, &v
);
758 if (status
!= BT_BTR_STATUS_OK
) {
759 BT_LOGW("Cannot read unsigned bit array for unsigned integer field: "
760 "btr-addr=%p, status=%s",
761 btr
, bt_btr_status_string(status
));
765 if (btr
->user
.cbs
.types
.unsigned_int
) {
766 BT_LOGV("Calling user function (unsigned integer).");
767 status
= btr
->user
.cbs
.types
.unsigned_int(v
,
768 btr
->cur_basic_field_type
, btr
->user
.data
);
769 BT_LOGV("User function returned: status=%s",
770 bt_btr_status_string(status
));
771 if (status
!= BT_BTR_STATUS_OK
) {
772 BT_LOGW("User function failed: "
773 "btr-addr=%p, status=%s",
774 btr
, bt_btr_status_string(status
));
784 enum bt_btr_status
read_basic_int_and_call_cb(struct bt_btr
*btr
,
785 const uint8_t *buf
, size_t at
)
787 return read_basic_int_and_call(btr
, buf
, at
, btr
->cur_basic_field_type
,
788 btr
->cur_basic_field_type
);
792 enum bt_btr_status
read_basic_enum_and_call_cb(struct bt_btr
*btr
,
793 const uint8_t *buf
, size_t at
)
795 struct bt_field_type
*int_field_type
;
796 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
798 int_field_type
= bt_field_type_enumeration_get_container_type(
799 btr
->cur_basic_field_type
);
800 assert(int_field_type
);
801 status
= read_basic_int_and_call(btr
, buf
, at
,
802 int_field_type
, btr
->cur_basic_field_type
);
803 bt_put(int_field_type
);
808 enum bt_btr_status
read_basic_type_and_call_continue(struct bt_btr
*btr
,
809 read_basic_and_call_cb_t read_basic_and_call_cb
)
814 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
816 if (!at_least_one_bit_left(btr
)) {
817 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
818 status
= BT_BTR_STATUS_EOF
;
822 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
823 if (field_size
< 1) {
824 BT_LOGW("Cannot get basic field type's size: "
825 "btr-addr=%p, ft-addr=%p",
826 btr
, btr
->cur_basic_field_type
);
827 status
= BT_BTR_STATUS_ERROR
;
831 available
= available_bits(btr
);
832 needed_bits
= field_size
- btr
->stitch
.at
;
833 BT_LOGV("Continuing basic field decoding: "
834 "btr-addr=%p, field-size=%" PRId64
", needed-size=%" PRId64
", "
835 "available-size=%zu",
836 btr
, field_size
, needed_bits
, available
);
837 if (needed_bits
<= available
) {
838 /* We have all the bits; append to stitch, then decode */
839 stitch_append_from_buf(btr
, needed_bits
);
840 status
= read_basic_and_call_cb(btr
, btr
->stitch
.buf
,
842 if (status
!= BT_BTR_STATUS_OK
) {
843 BT_LOGW("Cannot read basic field: "
844 "btr-addr=%p, ft-addr=%p, status=%s",
845 btr
, btr
->cur_basic_field_type
,
846 bt_btr_status_string(status
));
850 if (stack_empty(btr
->stack
)) {
851 /* Root is a basic type */
852 btr
->state
= BTR_STATE_DONE
;
854 /* Go to next field */
855 stack_top(btr
->stack
)->index
++;
856 btr
->state
= BTR_STATE_NEXT_FIELD
;
857 btr
->last_bo
= btr
->cur_bo
;
862 /* We are here; it means we don't have enough data to decode this */
863 BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer.");
864 stitch_append_from_remaining_buf(btr
);
865 status
= BT_BTR_STATUS_EOF
;
872 enum bt_btr_status
read_basic_type_and_call_begin(struct bt_btr
*btr
,
873 read_basic_and_call_cb_t read_basic_and_call_cb
)
877 enum bt_byte_order bo
;
878 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
880 if (!at_least_one_bit_left(btr
)) {
881 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
882 status
= BT_BTR_STATUS_EOF
;
886 field_size
= get_basic_field_type_size(btr
, btr
->cur_basic_field_type
);
887 if (field_size
< 1) {
888 BT_LOGW("Cannot get basic field type's size: "
889 "btr-addr=%p, ft-addr=%p",
890 btr
, btr
->cur_basic_field_type
);
891 status
= BT_BTR_STATUS_ERROR
;
895 bo
= bt_field_type_get_byte_order(btr
->cur_basic_field_type
);
896 status
= validate_contiguous_bo(btr
, bo
);
897 if (status
!= BT_BTR_STATUS_OK
) {
898 /* validate_contiguous_bo() logs errors */
902 available
= available_bits(btr
);
904 if (field_size
<= available
) {
905 /* We have all the bits; decode and set now */
906 status
= read_basic_and_call_cb(btr
, btr
->buf
.addr
,
907 buf_at_from_addr(btr
));
908 if (status
!= BT_BTR_STATUS_OK
) {
909 BT_LOGW("Cannot read basic field: "
910 "btr-addr=%p, ft-addr=%p, status=%s",
911 btr
, btr
->cur_basic_field_type
,
912 bt_btr_status_string(status
));
916 consume_bits(btr
, field_size
);
918 if (stack_empty(btr
->stack
)) {
919 /* Root is a basic type */
920 btr
->state
= BTR_STATE_DONE
;
922 /* Go to next field */
923 stack_top(btr
->stack
)->index
++;
924 btr
->state
= BTR_STATE_NEXT_FIELD
;
925 btr
->last_bo
= btr
->cur_bo
;
931 /* We are here; it means we don't have enough data to decode this */
932 BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer.");
933 stitch_set_from_remaining_buf(btr
);
934 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
935 status
= BT_BTR_STATUS_EOF
;
942 enum bt_btr_status
read_basic_int_type_and_call_begin(
945 return read_basic_type_and_call_begin(btr
, read_basic_int_and_call_cb
);
949 enum bt_btr_status
read_basic_int_type_and_call_continue(
952 return read_basic_type_and_call_continue(btr
,
953 read_basic_int_and_call_cb
);
957 enum bt_btr_status
read_basic_float_type_and_call_begin(
960 return read_basic_type_and_call_begin(btr
,
961 read_basic_float_and_call_cb
);
965 enum bt_btr_status
read_basic_float_type_and_call_continue(
968 return read_basic_type_and_call_continue(btr
,
969 read_basic_float_and_call_cb
);
973 enum bt_btr_status
read_basic_enum_type_and_call_begin(
976 return read_basic_type_and_call_begin(btr
,
977 read_basic_enum_and_call_cb
);
981 enum bt_btr_status
read_basic_enum_type_and_call_continue(
984 return read_basic_type_and_call_continue(btr
,
985 read_basic_enum_and_call_cb
);
989 enum bt_btr_status
read_basic_string_type_and_call(
990 struct bt_btr
*btr
, bool begin
)
993 const uint8_t *result
;
994 size_t available_bytes
;
995 const uint8_t *first_chr
;
996 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
998 if (!at_least_one_bit_left(btr
)) {
999 BT_LOGV("Reached end of data: btr-addr=%p", btr
);
1000 status
= BT_BTR_STATUS_EOF
;
1004 assert(buf_at_from_addr(btr
) % 8 == 0);
1005 available_bytes
= BITS_TO_BYTES_FLOOR(available_bits(btr
));
1006 buf_at_bytes
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr
));
1007 first_chr
= &btr
->buf
.addr
[buf_at_bytes
];
1008 result
= memchr(first_chr
, '\0', available_bytes
);
1010 if (begin
&& btr
->user
.cbs
.types
.string_begin
) {
1011 BT_LOGV("Calling user function (string, beginning).");
1012 status
= btr
->user
.cbs
.types
.string_begin(
1013 btr
->cur_basic_field_type
, btr
->user
.data
);
1014 BT_LOGV("User function returned: status=%s",
1015 bt_btr_status_string(status
));
1016 if (status
!= BT_BTR_STATUS_OK
) {
1017 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1018 btr
, bt_btr_status_string(status
));
1024 /* No null character yet */
1025 if (btr
->user
.cbs
.types
.string
) {
1026 BT_LOGV("Calling user function (substring).");
1027 status
= btr
->user
.cbs
.types
.string(
1028 (const char *) first_chr
,
1029 available_bytes
, btr
->cur_basic_field_type
,
1031 BT_LOGV("User function returned: status=%s",
1032 bt_btr_status_string(status
));
1033 if (status
!= BT_BTR_STATUS_OK
) {
1034 BT_LOGW("User function failed: "
1035 "btr-addr=%p, status=%s",
1036 btr
, bt_btr_status_string(status
));
1041 consume_bits(btr
, BYTES_TO_BITS(available_bytes
));
1042 btr
->state
= BTR_STATE_READ_BASIC_CONTINUE
;
1043 status
= BT_BTR_STATUS_EOF
;
1045 /* Found the null character */
1046 size_t result_len
= (size_t) (result
- first_chr
);
1048 if (btr
->user
.cbs
.types
.string
&& result_len
) {
1049 BT_LOGV("Calling user function (substring).");
1050 status
= btr
->user
.cbs
.types
.string(
1051 (const char *) first_chr
,
1052 result_len
, btr
->cur_basic_field_type
,
1054 BT_LOGV("User function returned: status=%s",
1055 bt_btr_status_string(status
));
1056 if (status
!= BT_BTR_STATUS_OK
) {
1057 BT_LOGW("User function failed: "
1058 "btr-addr=%p, status=%s",
1059 btr
, bt_btr_status_string(status
));
1064 if (btr
->user
.cbs
.types
.string_end
) {
1065 BT_LOGV("Calling user function (string, end).");
1066 status
= btr
->user
.cbs
.types
.string_end(
1067 btr
->cur_basic_field_type
, btr
->user
.data
);
1068 BT_LOGV("User function returned: status=%s",
1069 bt_btr_status_string(status
));
1070 if (status
!= BT_BTR_STATUS_OK
) {
1071 BT_LOGW("User function failed: "
1072 "btr-addr=%p, status=%s",
1073 btr
, bt_btr_status_string(status
));
1078 consume_bits(btr
, BYTES_TO_BITS(result_len
+ 1));
1080 if (stack_empty(btr
->stack
)) {
1081 /* Root is a basic type */
1082 btr
->state
= BTR_STATE_DONE
;
1084 /* Go to next field */
1085 stack_top(btr
->stack
)->index
++;
1086 btr
->state
= BTR_STATE_NEXT_FIELD
;
1087 btr
->last_bo
= btr
->cur_bo
;
1096 enum bt_btr_status
read_basic_begin_state(struct bt_btr
*btr
)
1098 enum bt_btr_status status
;
1100 assert(btr
->cur_basic_field_type
);
1102 switch (bt_field_type_get_type_id(btr
->cur_basic_field_type
)) {
1103 case BT_FIELD_TYPE_ID_INTEGER
:
1104 status
= read_basic_int_type_and_call_begin(btr
);
1106 case BT_FIELD_TYPE_ID_FLOAT
:
1107 status
= read_basic_float_type_and_call_begin(btr
);
1109 case BT_FIELD_TYPE_ID_ENUM
:
1110 status
= read_basic_enum_type_and_call_begin(btr
);
1112 case BT_FIELD_TYPE_ID_STRING
:
1113 status
= read_basic_string_type_and_call(btr
, true);
1116 BT_LOGF("Unknown basic field type ID: "
1117 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1118 btr
, btr
->cur_basic_field_type
,
1119 bt_field_type_id_string(
1120 bt_field_type_get_type_id(
1121 btr
->cur_basic_field_type
)));
1129 enum bt_btr_status
read_basic_continue_state(struct bt_btr
*btr
)
1131 enum bt_btr_status status
;
1133 assert(btr
->cur_basic_field_type
);
1135 switch (bt_field_type_get_type_id(btr
->cur_basic_field_type
)) {
1136 case BT_FIELD_TYPE_ID_INTEGER
:
1137 status
= read_basic_int_type_and_call_continue(btr
);
1139 case BT_FIELD_TYPE_ID_FLOAT
:
1140 status
= read_basic_float_type_and_call_continue(btr
);
1142 case BT_FIELD_TYPE_ID_ENUM
:
1143 status
= read_basic_enum_type_and_call_continue(btr
);
1145 case BT_FIELD_TYPE_ID_STRING
:
1146 status
= read_basic_string_type_and_call(btr
, false);
1149 BT_LOGF("Unknown basic field type ID: "
1150 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1151 btr
, btr
->cur_basic_field_type
,
1152 bt_field_type_id_string(
1153 bt_field_type_get_type_id(
1154 btr
->cur_basic_field_type
)));
1162 size_t bits_to_skip_to_align_to(struct bt_btr
*btr
, size_t align
)
1164 size_t aligned_packet_at
;
1166 aligned_packet_at
= ALIGN(packet_at(btr
), align
);
1167 return aligned_packet_at
- packet_at(btr
);
1171 enum bt_btr_status
align_type_state(struct bt_btr
*btr
,
1172 struct bt_field_type
*field_type
, enum btr_state next_state
)
1174 int field_alignment
;
1176 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1178 /* Get field's alignment */
1179 field_alignment
= bt_field_type_get_alignment(field_type
);
1180 if (field_alignment
< 0) {
1181 BT_LOGW("Cannot get field type's alignment: "
1182 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1184 bt_field_type_id_string(
1185 bt_field_type_get_type_id(field_type
)));
1186 status
= BT_BTR_STATUS_ERROR
;
1191 * 0 means "undefined" for variants; what we really want is 1
1194 if (field_alignment
== 0) {
1195 field_alignment
= 1;
1198 /* Compute how many bits we need to skip */
1199 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1201 /* Nothing to skip? aligned */
1202 if (skip_bits
== 0) {
1203 btr
->state
= next_state
;
1207 /* Make sure there's at least one bit left */
1208 if (!at_least_one_bit_left(btr
)) {
1209 status
= BT_BTR_STATUS_EOF
;
1213 /* Consume as many bits as possible in what's left */
1214 consume_bits(btr
, MIN(available_bits(btr
), skip_bits
));
1216 /* Are we done now? */
1217 skip_bits
= bits_to_skip_to_align_to(btr
, field_alignment
);
1218 if (skip_bits
== 0) {
1219 /* Yes: go to next state */
1220 btr
->state
= next_state
;
1223 /* No: need more data */
1224 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr
);
1225 status
= BT_BTR_STATUS_EOF
;
1233 bool is_compound_type(struct bt_field_type
*field_type
)
1235 enum bt_field_type_id id
= bt_field_type_get_type_id(field_type
);
1237 return id
== BT_FIELD_TYPE_ID_STRUCT
|| id
== BT_FIELD_TYPE_ID_ARRAY
||
1238 id
== BT_FIELD_TYPE_ID_SEQUENCE
|| id
== BT_FIELD_TYPE_ID_VARIANT
;
1242 enum bt_btr_status
next_field_state(struct bt_btr
*btr
)
1245 struct stack_entry
*top
;
1246 struct bt_field_type
*next_field_type
= NULL
;
1247 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1249 if (stack_empty(btr
->stack
)) {
1253 top
= stack_top(btr
->stack
);
1255 /* Are we done with this base type? */
1256 while (top
->index
== top
->base_len
) {
1257 if (btr
->user
.cbs
.types
.compound_end
) {
1258 BT_LOGV("Calling user function (compound, end).");
1259 status
= btr
->user
.cbs
.types
.compound_end(
1260 top
->base_type
, btr
->user
.data
);
1261 BT_LOGV("User function returned: status=%s",
1262 bt_btr_status_string(status
));
1263 if (status
!= BT_BTR_STATUS_OK
) {
1264 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1265 btr
, bt_btr_status_string(status
));
1270 stack_pop(btr
->stack
);
1272 /* Are we done with the root type? */
1273 if (stack_empty(btr
->stack
)) {
1274 btr
->state
= BTR_STATE_DONE
;
1278 top
= stack_top(btr
->stack
);
1282 /* Get next field's type */
1283 switch (bt_field_type_get_type_id(top
->base_type
)) {
1284 case BT_FIELD_TYPE_ID_STRUCT
:
1285 ret
= bt_field_type_structure_get_field_by_index(
1286 top
->base_type
, NULL
, &next_field_type
,
1289 next_field_type
= NULL
;
1292 case BT_FIELD_TYPE_ID_ARRAY
:
1294 bt_field_type_array_get_element_type(
1297 case BT_FIELD_TYPE_ID_SEQUENCE
:
1299 bt_field_type_sequence_get_element_type(
1302 case BT_FIELD_TYPE_ID_VARIANT
:
1303 /* Variant types are dynamic: query the user, he should know! */
1305 btr
->user
.cbs
.query
.get_variant_type(
1306 top
->base_type
, btr
->user
.data
);
1312 if (!next_field_type
) {
1313 BT_LOGW("Cannot get the field type of the next field: "
1314 "btr-addr=%p, base-ft-addr=%p, base-ft-id=%s, "
1316 btr
, top
->base_type
,
1317 bt_field_type_id_string(
1318 bt_field_type_get_type_id(top
->base_type
)),
1320 status
= BT_BTR_STATUS_ERROR
;
1324 if (is_compound_type(next_field_type
)) {
1325 if (btr
->user
.cbs
.types
.compound_begin
) {
1326 BT_LOGV("Calling user function (compound, begin).");
1327 status
= btr
->user
.cbs
.types
.compound_begin(
1328 next_field_type
, btr
->user
.data
);
1329 BT_LOGV("User function returned: status=%s",
1330 bt_btr_status_string(status
));
1331 if (status
!= BT_BTR_STATUS_OK
) {
1332 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1333 btr
, bt_btr_status_string(status
));
1338 ret
= stack_push_with_len(btr
, next_field_type
);
1340 /* stack_push_with_len() logs errors */
1341 status
= BT_BTR_STATUS_ERROR
;
1345 /* Next state: align a compound type */
1346 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
1348 /* Replace current basic field type */
1349 BT_LOGV("Replacing current basic field type: "
1350 "btr-addr=%p, cur-basic-ft-addr=%p, "
1351 "next-basic-ft-addr=%p",
1352 btr
, btr
->cur_basic_field_type
, next_field_type
);
1353 BT_MOVE(btr
->cur_basic_field_type
, next_field_type
);
1355 /* Next state: align a basic type */
1356 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1360 BT_PUT(next_field_type
);
1366 enum bt_btr_status
handle_state(struct bt_btr
*btr
)
1368 enum bt_btr_status status
= BT_BTR_STATUS_OK
;
1370 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1371 btr
, btr_state_string(btr
->state
));
1373 switch (btr
->state
) {
1374 case BTR_STATE_NEXT_FIELD
:
1375 status
= next_field_state(btr
);
1377 case BTR_STATE_ALIGN_BASIC
:
1378 status
= align_type_state(btr
, btr
->cur_basic_field_type
,
1379 BTR_STATE_READ_BASIC_BEGIN
);
1381 case BTR_STATE_ALIGN_COMPOUND
:
1382 status
= align_type_state(btr
, stack_top(btr
->stack
)->base_type
,
1383 BTR_STATE_NEXT_FIELD
);
1385 case BTR_STATE_READ_BASIC_BEGIN
:
1386 status
= read_basic_begin_state(btr
);
1388 case BTR_STATE_READ_BASIC_CONTINUE
:
1389 status
= read_basic_continue_state(btr
);
1391 case BTR_STATE_DONE
:
1395 BT_LOGV("Handled state: btr-addr=%p, status=%s",
1396 btr
, bt_btr_status_string(status
));
1400 struct bt_btr
*bt_btr_create(struct bt_btr_cbs cbs
, void *data
)
1404 BT_LOGD_STR("Creating binary type reader (BTR).");
1405 btr
= g_new0(struct bt_btr
, 1);
1407 BT_LOGE_STR("Failed to allocate one binary type reader.");
1411 btr
->stack
= stack_new();
1413 BT_LOGE_STR("Cannot create BTR's stack.");
1414 bt_btr_destroy(btr
);
1419 btr
->state
= BTR_STATE_NEXT_FIELD
;
1420 btr
->user
.cbs
= cbs
;
1421 btr
->user
.data
= data
;
1422 BT_LOGD("Created BTR: addr=%p", btr
);
1428 void bt_btr_destroy(struct bt_btr
*btr
)
1431 stack_destroy(btr
->stack
);
1434 BT_LOGD("Destroying BTR: addr=%p", btr
);
1435 BT_PUT(btr
->cur_basic_field_type
);
1440 void reset(struct bt_btr
*btr
)
1442 BT_LOGD("Resetting BTR: addr=%p", btr
);
1443 stack_clear(btr
->stack
);
1444 BT_PUT(btr
->cur_basic_field_type
);
1446 btr
->buf
.addr
= NULL
;
1447 btr
->last_bo
= BT_BYTE_ORDER_UNKNOWN
;
1451 void update_packet_offset(struct bt_btr
*btr
)
1453 BT_LOGV("Updating packet offset for next call: "
1454 "btr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1455 btr
, btr
->buf
.packet_offset
,
1456 btr
->buf
.packet_offset
+ btr
->buf
.at
);
1457 btr
->buf
.packet_offset
+= btr
->buf
.at
;
1460 size_t bt_btr_start(struct bt_btr
*btr
,
1461 struct bt_field_type
*type
, const uint8_t *buf
,
1462 size_t offset
, size_t packet_offset
, size_t sz
,
1463 enum bt_btr_status
*status
)
1468 assert(BYTES_TO_BITS(sz
) > offset
);
1470 btr
->buf
.addr
= buf
;
1471 btr
->buf
.offset
= offset
;
1473 btr
->buf
.packet_offset
= packet_offset
;
1474 btr
->buf
.buf_sz
= sz
;
1475 btr
->buf
.sz
= BYTES_TO_BITS(sz
) - offset
;
1476 *status
= BT_BTR_STATUS_OK
;
1478 BT_LOGV("Starting decoding: btr-addr=%p, ft-addr=%p, "
1479 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1480 "packet-offset=%zu",
1481 btr
, type
, buf
, sz
, offset
, packet_offset
);
1484 if (is_compound_type(type
)) {
1485 /* Compound type: push on visit stack */
1488 if (btr
->user
.cbs
.types
.compound_begin
) {
1489 BT_LOGV("Calling user function (compound, begin).");
1490 *status
= btr
->user
.cbs
.types
.compound_begin(
1491 type
, btr
->user
.data
);
1492 BT_LOGV("User function returned: status=%s",
1493 bt_btr_status_string(*status
));
1494 if (*status
!= BT_BTR_STATUS_OK
) {
1495 BT_LOGW("User function failed: btr-addr=%p, status=%s",
1496 btr
, bt_btr_status_string(*status
));
1501 stack_ret
= stack_push_with_len(btr
, type
);
1503 /* stack_push_with_len() logs errors */
1504 *status
= BT_BTR_STATUS_ERROR
;
1508 btr
->state
= BTR_STATE_ALIGN_COMPOUND
;
1510 /* Basic type: set as current basic type */
1511 btr
->cur_basic_field_type
= type
;
1512 bt_get(btr
->cur_basic_field_type
);
1513 btr
->state
= BTR_STATE_ALIGN_BASIC
;
1516 /* Run the machine! */
1517 BT_LOGV_STR("Running the state machine.");
1520 *status
= handle_state(btr
);
1521 if (*status
!= BT_BTR_STATUS_OK
||
1522 btr
->state
== BTR_STATE_DONE
) {
1527 /* Update packet offset for next time */
1528 update_packet_offset(btr
);
1534 size_t bt_btr_continue(struct bt_btr
*btr
,
1535 const uint8_t *buf
, size_t sz
,
1536 enum bt_btr_status
*status
)
1541 btr
->buf
.addr
= buf
;
1542 btr
->buf
.offset
= 0;
1544 btr
->buf
.buf_sz
= sz
;
1545 btr
->buf
.sz
= BYTES_TO_BITS(sz
);
1546 *status
= BT_BTR_STATUS_OK
;
1548 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1551 /* Continue running the machine */
1552 BT_LOGV_STR("Running the state machine.");
1555 *status
= handle_state(btr
);
1556 if (*status
!= BT_BTR_STATUS_OK
||
1557 btr
->state
== BTR_STATE_DONE
) {
1562 /* Update packet offset for next time */
1563 update_packet_offset(btr
);