2 * SPDX-License-Identifier: MIT
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
7 * Babeltrace - CTF binary field class reader (BFCR)
10 #define BT_COMP_LOG_SELF_COMP (bfcr->self_comp)
11 #define BT_LOG_OUTPUT_LEVEL (bfcr->log_level)
12 #define BT_LOG_TAG "PLUGIN/CTF/BFCR"
13 #include "logging/comp-logging.h"
21 #include "common/assert.h"
23 #include "compat/bitfield.h"
24 #include "common/common.h"
25 #include <babeltrace2/babeltrace.h>
26 #include "common/align.h"
30 #include "../metadata/ctf-meta.h"
32 #define DIV8(_x) ((_x) >> 3)
33 #define BYTES_TO_BITS(_x) ((_x) * 8)
34 #define BITS_TO_BYTES_FLOOR(_x) DIV8(_x)
35 #define BITS_TO_BYTES_CEIL(_x) DIV8((_x) + 7)
36 #define IN_BYTE_OFFSET(_at) ((_at) & 7)
38 /* A visit stack entry */
41 * Current class of base field, one of:
48 struct ctf_field_class
*base_class
;
50 /* Length of base field (always 1 for a variant class) */
53 /* Index of next field to read */
63 /* Entries (struct stack_entry) */
66 /* Number of active entries */
72 BFCR_STATE_NEXT_FIELD
,
73 BFCR_STATE_ALIGN_BASIC
,
74 BFCR_STATE_ALIGN_COMPOUND
,
75 BFCR_STATE_READ_BASIC_BEGIN
,
76 BFCR_STATE_READ_BASIC_CONTINUE
,
80 /* Binary class reader */
82 bt_logging_level log_level
;
85 bt_self_component
*self_comp
;
90 /* Current basic field class */
91 struct ctf_field_class
*cur_basic_field_class
;
94 enum bfcr_state state
;
97 * Last basic field class's byte order.
99 * This is used to detect errors since two contiguous basic
100 * classes for which the common boundary is not the boundary of
101 * a byte cannot have different byte orders.
103 * This is set to CTF_BYTE_ORDER_UNKNOWN on reset and when the last
104 * basic field class was a string class.
106 enum ctf_byte_order last_bo
;
108 /* Current byte order (copied to last_bo after a successful read) */
109 enum ctf_byte_order cur_bo
;
111 /* Stitch buffer infos */
116 /* Offset, within stitch buffer, of first bit */
119 /* Length (bits) of data in stitch buffer from offset */
123 /* User buffer infos */
128 /* Offset of data from address (bits) */
131 /* Current position from offset (bits) */
134 /* Offset of offset within whole packet (bits) */
135 size_t packet_offset
;
137 /* Data size in buffer (bits) */
140 /* Buffer size (bytes) */
146 /* Callback functions */
147 struct bt_bfcr_cbs cbs
;
155 const char *bfcr_state_string(enum bfcr_state state
)
158 case BFCR_STATE_NEXT_FIELD
:
160 case BFCR_STATE_ALIGN_BASIC
:
161 return "ALIGN_BASIC";
162 case BFCR_STATE_ALIGN_COMPOUND
:
163 return "ALIGN_COMPOUND";
164 case BFCR_STATE_READ_BASIC_BEGIN
:
165 return "READ_BASIC_BEGIN";
166 case BFCR_STATE_READ_BASIC_CONTINUE
:
167 return "READ_BASIC_CONTINUE";
168 case BFCR_STATE_DONE
:
176 struct stack
*stack_new(struct bt_bfcr
*bfcr
)
178 struct stack
*stack
= NULL
;
180 stack
= g_new0(struct stack
, 1);
182 BT_COMP_LOGE_STR("Failed to allocate one stack.");
187 stack
->entries
= g_array_new(FALSE
, TRUE
, sizeof(struct stack_entry
));
188 if (!stack
->entries
) {
189 BT_COMP_LOGE_STR("Failed to allocate a GArray.");
193 BT_COMP_LOGD("Created stack: addr=%p", stack
);
202 void stack_destroy(struct stack
*stack
)
204 struct bt_bfcr
*bfcr
;
211 BT_COMP_LOGD("Destroying stack: addr=%p", stack
);
213 if (stack
->entries
) {
214 g_array_free(stack
->entries
, TRUE
);
221 int stack_push(struct stack
*stack
, struct ctf_field_class
*base_class
,
224 struct stack_entry
*entry
;
225 struct bt_bfcr
*bfcr
;
227 BT_ASSERT_DBG(stack
);
228 BT_ASSERT_DBG(base_class
);
230 BT_COMP_LOGT("Pushing field class on stack: stack-addr=%p, "
231 "fc-addr=%p, fc-type=%d, base-length=%zu, "
232 "stack-size-before=%zu, stack-size-after=%zu",
233 stack
, base_class
, base_class
->type
,
234 base_len
, stack
->size
, stack
->size
+ 1);
236 if (stack
->entries
->len
== stack
->size
) {
237 g_array_set_size(stack
->entries
, stack
->size
+ 1);
240 entry
= &g_array_index(stack
->entries
, struct stack_entry
, stack
->size
);
241 entry
->base_class
= base_class
;
242 entry
->base_len
= base_len
;
249 int64_t get_compound_field_class_length(struct bt_bfcr
*bfcr
,
250 struct ctf_field_class
*fc
)
255 case CTF_FIELD_CLASS_TYPE_STRUCT
:
257 struct ctf_field_class_struct
*struct_fc
= (void *) fc
;
259 length
= (int64_t) struct_fc
->members
->len
;
262 case CTF_FIELD_CLASS_TYPE_VARIANT
:
264 /* Variant field classes always "contain" a single class */
268 case CTF_FIELD_CLASS_TYPE_ARRAY
:
270 struct ctf_field_class_array
*array_fc
= (void *) fc
;
272 length
= (int64_t) array_fc
->length
;
275 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
276 length
= bfcr
->user
.cbs
.query
.get_sequence_length(fc
,
287 int stack_push_with_len(struct bt_bfcr
*bfcr
, struct ctf_field_class
*base_class
)
290 int64_t length
= get_compound_field_class_length(bfcr
, base_class
);
293 BT_COMP_LOGW("Cannot get compound field class's field count: "
294 "bfcr-addr=%p, fc-addr=%p, fc-type=%d",
295 bfcr
, base_class
, base_class
->type
);
296 ret
= BT_BFCR_STATUS_ERROR
;
300 ret
= stack_push(bfcr
->stack
, base_class
, (size_t) length
);
307 unsigned int stack_size(struct stack
*stack
)
309 BT_ASSERT_DBG(stack
);
314 void stack_pop(struct stack
*stack
)
316 struct bt_bfcr
*bfcr
;
318 BT_ASSERT_DBG(stack
);
319 BT_ASSERT_DBG(stack_size(stack
));
321 BT_COMP_LOGT("Popping from stack: "
322 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
323 stack
, stack
->entries
->len
, stack
->entries
->len
- 1);
328 bool stack_empty(struct stack
*stack
)
330 return stack_size(stack
) == 0;
334 void stack_clear(struct stack
*stack
)
336 BT_ASSERT_DBG(stack
);
341 struct stack_entry
*stack_top(struct stack
*stack
)
343 BT_ASSERT_DBG(stack
);
344 BT_ASSERT_DBG(stack_size(stack
));
345 return &g_array_index(stack
->entries
, struct stack_entry
,
350 size_t available_bits(struct bt_bfcr
*bfcr
)
352 return bfcr
->buf
.sz
- bfcr
->buf
.at
;
356 void consume_bits(struct bt_bfcr
*bfcr
, size_t incr
)
358 BT_COMP_LOGT("Advancing cursor: bfcr-addr=%p, cur-before=%zu, cur-after=%zu",
359 bfcr
, bfcr
->buf
.at
, bfcr
->buf
.at
+ incr
);
360 bfcr
->buf
.at
+= incr
;
364 bool has_enough_bits(struct bt_bfcr
*bfcr
, size_t sz
)
366 return available_bits(bfcr
) >= sz
;
370 bool at_least_one_bit_left(struct bt_bfcr
*bfcr
)
372 return has_enough_bits(bfcr
, 1);
376 size_t packet_at(struct bt_bfcr
*bfcr
)
378 return bfcr
->buf
.packet_offset
+ bfcr
->buf
.at
;
382 size_t buf_at_from_addr(struct bt_bfcr
*bfcr
)
387 * ====== offset ===== (17)
389 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
391 * addr (0) ==== at ==== (12)
395 * =============================== (29)
397 return bfcr
->buf
.offset
+ bfcr
->buf
.at
;
401 void stitch_reset(struct bt_bfcr
*bfcr
)
403 bfcr
->stitch
.offset
= 0;
408 size_t stitch_at_from_addr(struct bt_bfcr
*bfcr
)
410 return bfcr
->stitch
.offset
+ bfcr
->stitch
.at
;
414 void stitch_append_from_buf(struct bt_bfcr
*bfcr
, size_t sz
)
416 size_t stitch_byte_at
;
425 BITS_TO_BYTES_FLOOR(stitch_at_from_addr(bfcr
));
426 buf_byte_at
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(bfcr
));
427 nb_bytes
= BITS_TO_BYTES_CEIL(sz
);
428 BT_ASSERT(nb_bytes
> 0);
429 BT_ASSERT(bfcr
->buf
.addr
);
430 memcpy(&bfcr
->stitch
.buf
[stitch_byte_at
], &bfcr
->buf
.addr
[buf_byte_at
],
432 bfcr
->stitch
.at
+= sz
;
433 consume_bits(bfcr
, sz
);
437 void stitch_append_from_remaining_buf(struct bt_bfcr
*bfcr
)
439 stitch_append_from_buf(bfcr
, available_bits(bfcr
));
443 void stitch_set_from_remaining_buf(struct bt_bfcr
*bfcr
)
446 bfcr
->stitch
.offset
= IN_BYTE_OFFSET(buf_at_from_addr(bfcr
));
447 stitch_append_from_remaining_buf(bfcr
);
451 void read_unsigned_bitfield(struct bt_bfcr
*bfcr
, const uint8_t *buf
, size_t at
,
452 unsigned int field_size
, enum ctf_byte_order bo
,
456 case CTF_BYTE_ORDER_BIG
:
457 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
459 case CTF_BYTE_ORDER_LITTLE
:
460 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
466 BT_COMP_LOGT("Read unsigned bit array: cur=%zu, size=%u, "
467 "bo=%d, val=%" PRIu64
, at
, field_size
, bo
, *v
);
471 void read_signed_bitfield(struct bt_bfcr
*bfcr
, const uint8_t *buf
, size_t at
,
472 unsigned int field_size
, enum ctf_byte_order bo
, int64_t *v
)
475 case CTF_BYTE_ORDER_BIG
:
476 bt_bitfield_read_be(buf
, uint8_t, at
, field_size
, v
);
478 case CTF_BYTE_ORDER_LITTLE
:
479 bt_bitfield_read_le(buf
, uint8_t, at
, field_size
, v
);
485 BT_COMP_LOGT("Read signed bit array: cur=%zu, size=%u, "
486 "bo=%d, val=%" PRId64
, at
, field_size
, bo
, *v
);
489 typedef enum bt_bfcr_status (* read_basic_and_call_cb_t
)(struct bt_bfcr
*,
490 const uint8_t *, size_t);
493 enum bt_bfcr_status
validate_contiguous_bo(struct bt_bfcr
*bfcr
,
494 enum ctf_byte_order next_bo
)
496 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
498 /* Always valid when at a byte boundary */
499 if (packet_at(bfcr
) % 8 == 0) {
503 /* Always valid if last byte order is unknown */
504 if (bfcr
->last_bo
== CTF_BYTE_ORDER_UNKNOWN
) {
508 /* Always valid if next byte order is unknown */
509 if (next_bo
== CTF_BYTE_ORDER_UNKNOWN
) {
513 /* Make sure last byte order is compatible with the next byte order */
514 switch (bfcr
->last_bo
) {
515 case CTF_BYTE_ORDER_BIG
:
516 if (next_bo
!= CTF_BYTE_ORDER_BIG
) {
517 status
= BT_BFCR_STATUS_ERROR
;
520 case CTF_BYTE_ORDER_LITTLE
:
521 if (next_bo
!= CTF_BYTE_ORDER_LITTLE
) {
522 status
= BT_BFCR_STATUS_ERROR
;
526 status
= BT_BFCR_STATUS_ERROR
;
531 BT_COMP_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
532 "bfcr-addr=%p, last-bo=%d, next-bo=%d",
533 bfcr
, bfcr
->last_bo
, next_bo
);
540 enum bt_bfcr_status
read_basic_float_and_call_cb(struct bt_bfcr
*bfcr
,
541 const uint8_t *buf
, size_t at
)
544 unsigned int field_size
;
545 enum ctf_byte_order bo
;
546 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
547 struct ctf_field_class_float
*fc
= (void *) bfcr
->cur_basic_field_class
;
550 field_size
= fc
->base
.size
;
551 bo
= fc
->base
.byte_order
;
554 switch (field_size
) {
563 read_unsigned_bitfield(bfcr
, buf
, at
, field_size
, bo
, &v
);
564 f32
.u
= (uint32_t) v
;
565 dblval
= (double) f32
.f
;
575 read_unsigned_bitfield(bfcr
, buf
, at
, field_size
, bo
, &f64
.u
);
580 /* Only 32-bit and 64-bit fields are supported currently */
584 BT_COMP_LOGT("Read floating point number value: bfcr=%p, cur=%zu, val=%f",
587 if (bfcr
->user
.cbs
.classes
.floating_point
) {
588 BT_COMP_LOGT("Calling user function (floating point number).");
589 status
= bfcr
->user
.cbs
.classes
.floating_point(dblval
,
590 bfcr
->cur_basic_field_class
, bfcr
->user
.data
);
591 BT_COMP_LOGT("User function returned: status=%s",
592 bt_bfcr_status_string(status
));
593 if (status
!= BT_BFCR_STATUS_OK
) {
594 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s",
595 bfcr
, bt_bfcr_status_string(status
));
603 enum bt_bfcr_status
read_basic_int_and_call_cb(struct bt_bfcr
*bfcr
,
604 const uint8_t *buf
, size_t at
)
606 unsigned int field_size
;
607 enum ctf_byte_order bo
;
608 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
609 struct ctf_field_class_int
*fc
= (void *) bfcr
->cur_basic_field_class
;
611 field_size
= fc
->base
.size
;
612 bo
= fc
->base
.byte_order
;
615 * Update current byte order now because we could be reading
616 * the integer value of an enumeration class, and thus we know
617 * here the actual supporting integer class's byte order.
624 read_signed_bitfield(bfcr
, buf
, at
, field_size
, bo
, &v
);
626 if (bfcr
->user
.cbs
.classes
.signed_int
) {
627 BT_COMP_LOGT("Calling user function (signed integer).");
628 status
= bfcr
->user
.cbs
.classes
.signed_int(v
,
629 bfcr
->cur_basic_field_class
, bfcr
->user
.data
);
630 BT_COMP_LOGT("User function returned: status=%s",
631 bt_bfcr_status_string(status
));
632 if (status
!= BT_BFCR_STATUS_OK
) {
633 BT_COMP_LOGW("User function failed: "
634 "bfcr-addr=%p, status=%s",
635 bfcr
, bt_bfcr_status_string(status
));
641 read_unsigned_bitfield(bfcr
, buf
, at
, field_size
, bo
, &v
);
643 if (bfcr
->user
.cbs
.classes
.unsigned_int
) {
644 BT_COMP_LOGT("Calling user function (unsigned integer).");
645 status
= bfcr
->user
.cbs
.classes
.unsigned_int(v
,
646 bfcr
->cur_basic_field_class
, bfcr
->user
.data
);
647 BT_COMP_LOGT("User function returned: status=%s",
648 bt_bfcr_status_string(status
));
649 if (status
!= BT_BFCR_STATUS_OK
) {
650 BT_COMP_LOGW("User function failed: "
651 "bfcr-addr=%p, status=%s",
652 bfcr
, bt_bfcr_status_string(status
));
661 enum bt_bfcr_status
read_bit_array_class_and_call_continue(struct bt_bfcr
*bfcr
,
662 read_basic_and_call_cb_t read_basic_and_call_cb
)
666 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
667 struct ctf_field_class_bit_array
*fc
=
668 (void *) bfcr
->cur_basic_field_class
;
670 if (!at_least_one_bit_left(bfcr
)) {
671 BT_COMP_LOGT("Reached end of data: bfcr-addr=%p", bfcr
);
672 status
= BT_BFCR_STATUS_EOF
;
676 available
= available_bits(bfcr
);
677 needed_bits
= fc
->size
- bfcr
->stitch
.at
;
678 BT_COMP_LOGT("Continuing basic field decoding: "
679 "bfcr-addr=%p, field-size=%u, needed-size=%zu, "
680 "available-size=%zu",
681 bfcr
, fc
->size
, needed_bits
, available
);
682 if (needed_bits
<= available
) {
683 /* We have all the bits; append to stitch, then decode */
684 stitch_append_from_buf(bfcr
, needed_bits
);
685 status
= read_basic_and_call_cb(bfcr
, bfcr
->stitch
.buf
,
686 bfcr
->stitch
.offset
);
687 if (status
!= BT_BFCR_STATUS_OK
) {
688 BT_COMP_LOGW("Cannot read basic field: "
689 "bfcr-addr=%p, fc-addr=%p, status=%s",
690 bfcr
, bfcr
->cur_basic_field_class
,
691 bt_bfcr_status_string(status
));
695 if (stack_empty(bfcr
->stack
)) {
696 /* Root is a basic class */
697 bfcr
->state
= BFCR_STATE_DONE
;
699 /* Go to next field */
700 stack_top(bfcr
->stack
)->index
++;
701 bfcr
->state
= BFCR_STATE_NEXT_FIELD
;
702 bfcr
->last_bo
= bfcr
->cur_bo
;
707 /* We are here; it means we don't have enough data to decode this */
708 BT_COMP_LOGT_STR("Not enough data to read the next basic field: appending to stitch buffer.");
709 stitch_append_from_remaining_buf(bfcr
);
710 status
= BT_BFCR_STATUS_EOF
;
717 enum bt_bfcr_status
read_bit_array_class_and_call_begin(struct bt_bfcr
*bfcr
,
718 read_basic_and_call_cb_t read_basic_and_call_cb
)
721 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
722 struct ctf_field_class_bit_array
*fc
=
723 (void *) bfcr
->cur_basic_field_class
;
725 if (!at_least_one_bit_left(bfcr
)) {
726 BT_COMP_LOGT("Reached end of data: bfcr-addr=%p", bfcr
);
727 status
= BT_BFCR_STATUS_EOF
;
731 status
= validate_contiguous_bo(bfcr
, fc
->byte_order
);
732 if (status
!= BT_BFCR_STATUS_OK
) {
733 /* validate_contiguous_bo() logs errors */
737 available
= available_bits(bfcr
);
739 if (fc
->size
<= available
) {
740 /* We have all the bits; decode and set now */
741 BT_ASSERT_DBG(bfcr
->buf
.addr
);
742 status
= read_basic_and_call_cb(bfcr
, bfcr
->buf
.addr
,
743 buf_at_from_addr(bfcr
));
744 if (status
!= BT_BFCR_STATUS_OK
) {
745 BT_COMP_LOGW("Cannot read basic field: "
746 "bfcr-addr=%p, fc-addr=%p, status=%s",
747 bfcr
, bfcr
->cur_basic_field_class
,
748 bt_bfcr_status_string(status
));
752 consume_bits(bfcr
, fc
->size
);
754 if (stack_empty(bfcr
->stack
)) {
755 /* Root is a basic class */
756 bfcr
->state
= BFCR_STATE_DONE
;
758 /* Go to next field */
759 stack_top(bfcr
->stack
)->index
++;
760 bfcr
->state
= BFCR_STATE_NEXT_FIELD
;
761 bfcr
->last_bo
= bfcr
->cur_bo
;
767 /* We are here; it means we don't have enough data to decode this */
768 BT_COMP_LOGT_STR("Not enough data to read the next basic field: setting stitch buffer.");
769 stitch_set_from_remaining_buf(bfcr
);
770 bfcr
->state
= BFCR_STATE_READ_BASIC_CONTINUE
;
771 status
= BT_BFCR_STATUS_EOF
;
778 enum bt_bfcr_status
read_basic_int_class_and_call_begin(
779 struct bt_bfcr
*bfcr
)
781 return read_bit_array_class_and_call_begin(bfcr
, read_basic_int_and_call_cb
);
785 enum bt_bfcr_status
read_basic_int_class_and_call_continue(
786 struct bt_bfcr
*bfcr
)
788 return read_bit_array_class_and_call_continue(bfcr
,
789 read_basic_int_and_call_cb
);
793 enum bt_bfcr_status
read_basic_float_class_and_call_begin(
794 struct bt_bfcr
*bfcr
)
796 return read_bit_array_class_and_call_begin(bfcr
,
797 read_basic_float_and_call_cb
);
801 enum bt_bfcr_status
read_basic_float_class_and_call_continue(
802 struct bt_bfcr
*bfcr
)
804 return read_bit_array_class_and_call_continue(bfcr
,
805 read_basic_float_and_call_cb
);
809 enum bt_bfcr_status
read_basic_string_class_and_call(
810 struct bt_bfcr
*bfcr
, bool begin
)
813 const uint8_t *result
;
814 size_t available_bytes
;
815 const uint8_t *first_chr
;
816 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
818 if (!at_least_one_bit_left(bfcr
)) {
819 BT_COMP_LOGT("Reached end of data: bfcr-addr=%p", bfcr
);
820 status
= BT_BFCR_STATUS_EOF
;
824 BT_ASSERT_DBG(buf_at_from_addr(bfcr
) % 8 == 0);
825 available_bytes
= BITS_TO_BYTES_FLOOR(available_bits(bfcr
));
826 buf_at_bytes
= BITS_TO_BYTES_FLOOR(buf_at_from_addr(bfcr
));
827 BT_ASSERT_DBG(bfcr
->buf
.addr
);
828 first_chr
= &bfcr
->buf
.addr
[buf_at_bytes
];
829 result
= memchr(first_chr
, '\0', available_bytes
);
831 if (begin
&& bfcr
->user
.cbs
.classes
.string_begin
) {
832 BT_COMP_LOGT("Calling user function (string, beginning).");
833 status
= bfcr
->user
.cbs
.classes
.string_begin(
834 bfcr
->cur_basic_field_class
, bfcr
->user
.data
);
835 BT_COMP_LOGT("User function returned: status=%s",
836 bt_bfcr_status_string(status
));
837 if (status
!= BT_BFCR_STATUS_OK
) {
838 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s",
839 bfcr
, bt_bfcr_status_string(status
));
845 /* No null character yet */
846 if (bfcr
->user
.cbs
.classes
.string
) {
847 BT_COMP_LOGT("Calling user function (substring).");
848 status
= bfcr
->user
.cbs
.classes
.string(
849 (const char *) first_chr
,
850 available_bytes
, bfcr
->cur_basic_field_class
,
852 BT_COMP_LOGT("User function returned: status=%s",
853 bt_bfcr_status_string(status
));
854 if (status
!= BT_BFCR_STATUS_OK
) {
855 BT_COMP_LOGW("User function failed: "
856 "bfcr-addr=%p, status=%s",
857 bfcr
, bt_bfcr_status_string(status
));
862 consume_bits(bfcr
, BYTES_TO_BITS(available_bytes
));
863 bfcr
->state
= BFCR_STATE_READ_BASIC_CONTINUE
;
864 status
= BT_BFCR_STATUS_EOF
;
866 /* Found the null character */
867 size_t result_len
= (size_t) (result
- first_chr
);
869 if (bfcr
->user
.cbs
.classes
.string
&& result_len
) {
870 BT_COMP_LOGT("Calling user function (substring).");
871 status
= bfcr
->user
.cbs
.classes
.string(
872 (const char *) first_chr
,
873 result_len
, bfcr
->cur_basic_field_class
,
875 BT_COMP_LOGT("User function returned: status=%s",
876 bt_bfcr_status_string(status
));
877 if (status
!= BT_BFCR_STATUS_OK
) {
878 BT_COMP_LOGW("User function failed: "
879 "bfcr-addr=%p, status=%s",
880 bfcr
, bt_bfcr_status_string(status
));
885 if (bfcr
->user
.cbs
.classes
.string_end
) {
886 BT_COMP_LOGT("Calling user function (string, end).");
887 status
= bfcr
->user
.cbs
.classes
.string_end(
888 bfcr
->cur_basic_field_class
, bfcr
->user
.data
);
889 BT_COMP_LOGT("User function returned: status=%s",
890 bt_bfcr_status_string(status
));
891 if (status
!= BT_BFCR_STATUS_OK
) {
892 BT_COMP_LOGW("User function failed: "
893 "bfcr-addr=%p, status=%s",
894 bfcr
, bt_bfcr_status_string(status
));
899 consume_bits(bfcr
, BYTES_TO_BITS(result_len
+ 1));
901 if (stack_empty(bfcr
->stack
)) {
902 /* Root is a basic class */
903 bfcr
->state
= BFCR_STATE_DONE
;
905 /* Go to next field */
906 stack_top(bfcr
->stack
)->index
++;
907 bfcr
->state
= BFCR_STATE_NEXT_FIELD
;
908 bfcr
->last_bo
= bfcr
->cur_bo
;
917 enum bt_bfcr_status
read_basic_begin_state(struct bt_bfcr
*bfcr
)
919 enum bt_bfcr_status status
;
921 BT_ASSERT_DBG(bfcr
->cur_basic_field_class
);
923 switch (bfcr
->cur_basic_field_class
->type
) {
924 case CTF_FIELD_CLASS_TYPE_INT
:
925 case CTF_FIELD_CLASS_TYPE_ENUM
:
926 status
= read_basic_int_class_and_call_begin(bfcr
);
928 case CTF_FIELD_CLASS_TYPE_FLOAT
:
929 status
= read_basic_float_class_and_call_begin(bfcr
);
931 case CTF_FIELD_CLASS_TYPE_STRING
:
932 status
= read_basic_string_class_and_call(bfcr
, true);
942 enum bt_bfcr_status
read_basic_continue_state(struct bt_bfcr
*bfcr
)
944 enum bt_bfcr_status status
;
946 BT_ASSERT_DBG(bfcr
->cur_basic_field_class
);
948 switch (bfcr
->cur_basic_field_class
->type
) {
949 case CTF_FIELD_CLASS_TYPE_INT
:
950 case CTF_FIELD_CLASS_TYPE_ENUM
:
951 status
= read_basic_int_class_and_call_continue(bfcr
);
953 case CTF_FIELD_CLASS_TYPE_FLOAT
:
954 status
= read_basic_float_class_and_call_continue(bfcr
);
956 case CTF_FIELD_CLASS_TYPE_STRING
:
957 status
= read_basic_string_class_and_call(bfcr
, false);
967 size_t bits_to_skip_to_align_to(struct bt_bfcr
*bfcr
, size_t align
)
969 size_t aligned_packet_at
;
971 aligned_packet_at
= ALIGN(packet_at(bfcr
), align
);
972 return aligned_packet_at
- packet_at(bfcr
);
976 enum bt_bfcr_status
align_class_state(struct bt_bfcr
*bfcr
,
977 struct ctf_field_class
*field_class
, enum bfcr_state next_state
)
979 unsigned int field_alignment
;
981 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
983 /* Get field's alignment */
984 field_alignment
= field_class
->alignment
;
987 * 0 means "undefined" for variants; what we really want is 1
990 BT_ASSERT_DBG(field_alignment
>= 1);
992 /* Compute how many bits we need to skip */
993 skip_bits
= bits_to_skip_to_align_to(bfcr
, (size_t) field_alignment
);
995 /* Nothing to skip? aligned */
996 if (skip_bits
== 0) {
997 bfcr
->state
= next_state
;
1001 /* Make sure there's at least one bit left */
1002 if (!at_least_one_bit_left(bfcr
)) {
1003 status
= BT_BFCR_STATUS_EOF
;
1007 /* Consume as many bits as possible in what's left */
1008 consume_bits(bfcr
, MIN(available_bits(bfcr
), skip_bits
));
1010 /* Are we done now? */
1011 skip_bits
= bits_to_skip_to_align_to(bfcr
, field_alignment
);
1012 if (skip_bits
== 0) {
1013 /* Yes: go to next state */
1014 bfcr
->state
= next_state
;
1017 /* No: need more data */
1018 BT_COMP_LOGT("Reached end of data when aligning: bfcr-addr=%p", bfcr
);
1019 status
= BT_BFCR_STATUS_EOF
;
1027 enum bt_bfcr_status
next_field_state(struct bt_bfcr
*bfcr
)
1030 struct stack_entry
*top
;
1031 struct ctf_field_class
*next_field_class
= NULL
;
1032 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
1034 if (stack_empty(bfcr
->stack
)) {
1038 top
= stack_top(bfcr
->stack
);
1040 /* Are we done with this base class? */
1041 while (top
->index
== top
->base_len
) {
1042 if (bfcr
->user
.cbs
.classes
.compound_end
) {
1043 BT_COMP_LOGT("Calling user function (compound, end).");
1044 status
= bfcr
->user
.cbs
.classes
.compound_end(
1045 top
->base_class
, bfcr
->user
.data
);
1046 BT_COMP_LOGT("User function returned: status=%s",
1047 bt_bfcr_status_string(status
));
1048 if (status
!= BT_BFCR_STATUS_OK
) {
1049 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s",
1050 bfcr
, bt_bfcr_status_string(status
));
1055 stack_pop(bfcr
->stack
);
1057 /* Are we done with the root class? */
1058 if (stack_empty(bfcr
->stack
)) {
1059 bfcr
->state
= BFCR_STATE_DONE
;
1063 top
= stack_top(bfcr
->stack
);
1067 /* Get next field's class */
1068 switch (top
->base_class
->type
) {
1069 case CTF_FIELD_CLASS_TYPE_STRUCT
:
1070 next_field_class
= ctf_field_class_struct_borrow_member_by_index(
1071 (void *) top
->base_class
, (uint64_t) top
->index
)->fc
;
1073 case CTF_FIELD_CLASS_TYPE_ARRAY
:
1074 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1076 struct ctf_field_class_array_base
*array_fc
=
1077 (void *) top
->base_class
;
1079 next_field_class
= array_fc
->elem_fc
;
1082 case CTF_FIELD_CLASS_TYPE_VARIANT
:
1083 /* Variant classes are dynamic: the user should know! */
1085 bfcr
->user
.cbs
.query
.borrow_variant_selected_field_class(
1086 top
->base_class
, bfcr
->user
.data
);
1092 if (!next_field_class
) {
1093 BT_COMP_LOGW("Cannot get the field class of the next field: "
1094 "bfcr-addr=%p, base-fc-addr=%p, base-fc-type=%d, "
1096 bfcr
, top
->base_class
, top
->base_class
->type
,
1098 status
= BT_BFCR_STATUS_ERROR
;
1102 if (next_field_class
->is_compound
) {
1103 if (bfcr
->user
.cbs
.classes
.compound_begin
) {
1104 BT_COMP_LOGT("Calling user function (compound, begin).");
1105 status
= bfcr
->user
.cbs
.classes
.compound_begin(
1106 next_field_class
, bfcr
->user
.data
);
1107 BT_COMP_LOGT("User function returned: status=%s",
1108 bt_bfcr_status_string(status
));
1109 if (status
!= BT_BFCR_STATUS_OK
) {
1110 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s",
1111 bfcr
, bt_bfcr_status_string(status
));
1116 ret
= stack_push_with_len(bfcr
, next_field_class
);
1118 /* stack_push_with_len() logs errors */
1119 status
= BT_BFCR_STATUS_ERROR
;
1123 /* Next state: align a compound class */
1124 bfcr
->state
= BFCR_STATE_ALIGN_COMPOUND
;
1126 /* Replace current basic field class */
1127 BT_COMP_LOGT("Replacing current basic field class: "
1128 "bfcr-addr=%p, cur-basic-fc-addr=%p, "
1129 "next-basic-fc-addr=%p",
1130 bfcr
, bfcr
->cur_basic_field_class
, next_field_class
);
1131 bfcr
->cur_basic_field_class
= next_field_class
;
1133 /* Next state: align a basic class */
1134 bfcr
->state
= BFCR_STATE_ALIGN_BASIC
;
1142 enum bt_bfcr_status
handle_state(struct bt_bfcr
*bfcr
)
1144 enum bt_bfcr_status status
= BT_BFCR_STATUS_OK
;
1146 BT_COMP_LOGT("Handling state: bfcr-addr=%p, state=%s",
1147 bfcr
, bfcr_state_string(bfcr
->state
));
1149 switch (bfcr
->state
) {
1150 case BFCR_STATE_NEXT_FIELD
:
1151 status
= next_field_state(bfcr
);
1153 case BFCR_STATE_ALIGN_BASIC
:
1154 status
= align_class_state(bfcr
, bfcr
->cur_basic_field_class
,
1155 BFCR_STATE_READ_BASIC_BEGIN
);
1157 case BFCR_STATE_ALIGN_COMPOUND
:
1158 status
= align_class_state(bfcr
, stack_top(bfcr
->stack
)->base_class
,
1159 BFCR_STATE_NEXT_FIELD
);
1161 case BFCR_STATE_READ_BASIC_BEGIN
:
1162 status
= read_basic_begin_state(bfcr
);
1164 case BFCR_STATE_READ_BASIC_CONTINUE
:
1165 status
= read_basic_continue_state(bfcr
);
1167 case BFCR_STATE_DONE
:
1171 BT_COMP_LOGT("Handled state: bfcr-addr=%p, status=%s",
1172 bfcr
, bt_bfcr_status_string(status
));
1177 struct bt_bfcr
*bt_bfcr_create(struct bt_bfcr_cbs cbs
, void *data
,
1178 bt_logging_level log_level
, bt_self_component
*self_comp
)
1180 struct bt_bfcr
*bfcr
;
1182 BT_COMP_LOG_CUR_LVL(BT_LOG_DEBUG
, log_level
, self_comp
,
1183 "Creating binary field class reader (BFCR).");
1184 bfcr
= g_new0(struct bt_bfcr
, 1);
1186 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, log_level
, self_comp
,
1187 "Failed to allocate one binary class reader.");
1191 bfcr
->log_level
= log_level
;
1192 bfcr
->self_comp
= self_comp
;
1193 bfcr
->stack
= stack_new(bfcr
);
1195 BT_COMP_LOGE_STR("Cannot create BFCR's stack.");
1196 bt_bfcr_destroy(bfcr
);
1201 bfcr
->state
= BFCR_STATE_NEXT_FIELD
;
1202 bfcr
->user
.cbs
= cbs
;
1203 bfcr
->user
.data
= data
;
1204 BT_COMP_LOGD("Created BFCR: addr=%p", bfcr
);
1211 void bt_bfcr_destroy(struct bt_bfcr
*bfcr
)
1214 stack_destroy(bfcr
->stack
);
1217 BT_COMP_LOGD("Destroying BFCR: addr=%p", bfcr
);
1222 void reset(struct bt_bfcr
*bfcr
)
1224 BT_COMP_LOGD("Resetting BFCR: addr=%p", bfcr
);
1225 stack_clear(bfcr
->stack
);
1227 bfcr
->buf
.addr
= NULL
;
1228 bfcr
->last_bo
= CTF_BYTE_ORDER_UNKNOWN
;
1232 void update_packet_offset(struct bt_bfcr
*bfcr
)
1234 BT_COMP_LOGT("Updating packet offset for next call: "
1235 "bfcr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1236 bfcr
, bfcr
->buf
.packet_offset
,
1237 bfcr
->buf
.packet_offset
+ bfcr
->buf
.at
);
1238 bfcr
->buf
.packet_offset
+= bfcr
->buf
.at
;
1242 size_t bt_bfcr_start(struct bt_bfcr
*bfcr
,
1243 struct ctf_field_class
*cls
, const uint8_t *buf
,
1244 size_t offset
, size_t packet_offset
, size_t sz
,
1245 enum bt_bfcr_status
*status
)
1247 BT_ASSERT_DBG(bfcr
);
1248 BT_ASSERT_DBG(BYTES_TO_BITS(sz
) >= offset
);
1250 bfcr
->buf
.addr
= buf
;
1251 bfcr
->buf
.offset
= offset
;
1253 bfcr
->buf
.packet_offset
= packet_offset
;
1254 bfcr
->buf
.buf_sz
= sz
;
1255 bfcr
->buf
.sz
= BYTES_TO_BITS(sz
) - offset
;
1256 *status
= BT_BFCR_STATUS_OK
;
1258 BT_COMP_LOGT("Starting decoding: bfcr-addr=%p, fc-addr=%p, "
1259 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1260 "packet-offset=%zu",
1261 bfcr
, cls
, buf
, sz
, offset
, packet_offset
);
1263 /* Set root class */
1264 if (cls
->is_compound
) {
1265 /* Compound class: push on visit stack */
1268 if (bfcr
->user
.cbs
.classes
.compound_begin
) {
1269 BT_COMP_LOGT("Calling user function (compound, begin).");
1270 *status
= bfcr
->user
.cbs
.classes
.compound_begin(
1271 cls
, bfcr
->user
.data
);
1272 BT_COMP_LOGT("User function returned: status=%s",
1273 bt_bfcr_status_string(*status
));
1274 if (*status
!= BT_BFCR_STATUS_OK
) {
1275 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s",
1276 bfcr
, bt_bfcr_status_string(*status
));
1281 stack_ret
= stack_push_with_len(bfcr
, cls
);
1283 /* stack_push_with_len() logs errors */
1284 *status
= BT_BFCR_STATUS_ERROR
;
1288 bfcr
->state
= BFCR_STATE_ALIGN_COMPOUND
;
1290 /* Basic class: set as current basic class */
1291 bfcr
->cur_basic_field_class
= cls
;
1292 bfcr
->state
= BFCR_STATE_ALIGN_BASIC
;
1295 /* Run the machine! */
1296 BT_COMP_LOGT_STR("Running the state machine.");
1299 *status
= handle_state(bfcr
);
1300 if (*status
!= BT_BFCR_STATUS_OK
||
1301 bfcr
->state
== BFCR_STATE_DONE
) {
1306 /* Update packet offset for next time */
1307 update_packet_offset(bfcr
);
1310 return bfcr
->buf
.at
;
1314 size_t bt_bfcr_continue(struct bt_bfcr
*bfcr
, const uint8_t *buf
, size_t sz
,
1315 enum bt_bfcr_status
*status
)
1317 BT_ASSERT_DBG(bfcr
);
1319 BT_ASSERT_DBG(sz
> 0);
1320 bfcr
->buf
.addr
= buf
;
1321 bfcr
->buf
.offset
= 0;
1323 bfcr
->buf
.buf_sz
= sz
;
1324 bfcr
->buf
.sz
= BYTES_TO_BITS(sz
);
1325 *status
= BT_BFCR_STATUS_OK
;
1327 BT_COMP_LOGT("Continuing decoding: bfcr-addr=%p, buf-addr=%p, buf-size=%zu",
1330 /* Continue running the machine */
1331 BT_COMP_LOGT_STR("Running the state machine.");
1334 *status
= handle_state(bfcr
);
1335 if (*status
!= BT_BFCR_STATUS_OK
||
1336 bfcr
->state
== BFCR_STATE_DONE
) {
1341 /* Update packet offset for next time */
1342 update_packet_offset(bfcr
);
1343 return bfcr
->buf
.at
;
1347 void bt_bfcr_set_unsigned_int_cb(struct bt_bfcr
*bfcr
,
1348 bt_bfcr_unsigned_int_cb_func cb
)
1350 BT_ASSERT_DBG(bfcr
);
1352 bfcr
->user
.cbs
.classes
.unsigned_int
= cb
;