Sort includes in C++ files
[babeltrace.git] / src / plugins / ctf / common / bfcr / bfcr.cpp
CommitLineData
5cd6d0e5 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
5cd6d0e5
PP
3 *
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
6 *
0235b0db 7 * Babeltrace - CTF binary field class reader (BFCR)
5cd6d0e5
PP
8 */
9
c802cacb
SM
10#include <glib.h>
11#include <inttypes.h>
12#include <stdbool.h>
13#include <stddef.h>
14#include <stdint.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19#include <babeltrace2/babeltrace.h>
20
c4a714d2 21#define BT_COMP_LOG_SELF_COMP (bfcr->self_comp)
4164020e
SM
22#define BT_LOG_OUTPUT_LEVEL (bfcr->log_level)
23#define BT_LOG_TAG "PLUGIN/CTF/BFCR"
d9c39b0a 24#include "logging/comp-logging.h"
5cd6d0e5 25
c802cacb 26#include "common/align.h"
578e048b 27#include "common/assert.h"
578e048b 28#include "common/common.h"
c802cacb 29#include "compat/bitfield.h"
5cd6d0e5 30
087cd0f5 31#include "../metadata/ctf-meta.hpp"
c802cacb 32#include "bfcr.hpp"
5cd6d0e5 33
4164020e
SM
34#define DIV8(_x) ((_x) >> 3)
35#define BYTES_TO_BITS(_x) ((_x) *8)
36#define BITS_TO_BYTES_FLOOR(_x) DIV8(_x)
37#define BITS_TO_BYTES_CEIL(_x) DIV8((_x) + 7)
38#define IN_BYTE_OFFSET(_at) ((_at) &7)
5cd6d0e5
PP
39
40/* A visit stack entry */
4164020e
SM
41struct stack_entry
42{
43 /*
44 * Current class of base field, one of:
45 *
46 * * Structure
47 * * Array
48 * * Sequence
49 * * Variant
50 */
51 struct ctf_field_class *base_class;
52
53 /* Length of base field (always 1 for a variant class) */
54 int64_t base_len;
55
56 /* Index of next field to read */
57 int64_t index;
5cd6d0e5
PP
58};
59
80870e64
PP
60struct bt_bfcr;
61
5cd6d0e5 62/* Visit stack */
4164020e
SM
63struct stack
64{
65 struct bt_bfcr *bfcr;
80870e64 66
4164020e
SM
67 /* Entries (struct stack_entry) */
68 GArray *entries;
5cd6d0e5 69
4164020e
SM
70 /* Number of active entries */
71 size_t size;
5cd6d0e5
PP
72};
73
74/* Reading states */
4164020e
SM
75enum bfcr_state
76{
77 BFCR_STATE_NEXT_FIELD,
78 BFCR_STATE_ALIGN_BASIC,
79 BFCR_STATE_ALIGN_COMPOUND,
80 BFCR_STATE_READ_BASIC_BEGIN,
81 BFCR_STATE_READ_BASIC_CONTINUE,
82 BFCR_STATE_DONE,
5cd6d0e5
PP
83};
84
85/* Binary class reader */
4164020e
SM
86struct bt_bfcr
87{
88 bt_logging_level log_level;
89
90 /* Weak */
91 bt_self_component *self_comp;
92
93 /* BFCR stack */
94 struct stack *stack;
95
96 /* Current basic field class */
97 struct ctf_field_class *cur_basic_field_class;
98
99 /* Current state */
100 enum bfcr_state state;
101
102 /*
103 * Last basic field class's byte order.
104 *
105 * This is used to detect errors since two contiguous basic
106 * classes for which the common boundary is not the boundary of
107 * a byte cannot have different byte orders.
108 *
109 * This is set to CTF_BYTE_ORDER_UNKNOWN on reset and when the last
110 * basic field class was a string class.
111 */
112 enum ctf_byte_order last_bo;
113
114 /* Current byte order (copied to last_bo after a successful read) */
115 enum ctf_byte_order cur_bo;
116
117 /* Stitch buffer infos */
118 struct
119 {
120 /* Stitch buffer */
121 uint8_t buf[16];
122
123 /* Offset, within stitch buffer, of first bit */
124 size_t offset;
125
126 /* Length (bits) of data in stitch buffer from offset */
127 size_t at;
128 } stitch;
129
130 /* User buffer infos */
131 struct
132 {
133 /* Address */
134 const uint8_t *addr;
135
136 /* Offset of data from address (bits) */
137 size_t offset;
138
139 /* Current position from offset (bits) */
140 size_t at;
141
142 /* Offset of offset within whole packet (bits) */
143 size_t packet_offset;
144
145 /* Data size in buffer (bits) */
146 size_t sz;
147
148 /* Buffer size (bytes) */
149 size_t buf_sz;
150 } buf;
151
152 /* User stuff */
153 struct
154 {
155 /* Callback functions */
156 struct bt_bfcr_cbs cbs;
157
158 /* Private data */
159 void *data;
160 } user;
5cd6d0e5
PP
161};
162
4164020e 163static inline const char *bfcr_state_string(enum bfcr_state state)
5cd6d0e5 164{
4164020e
SM
165 switch (state) {
166 case BFCR_STATE_NEXT_FIELD:
167 return "NEXT_FIELD";
168 case BFCR_STATE_ALIGN_BASIC:
169 return "ALIGN_BASIC";
170 case BFCR_STATE_ALIGN_COMPOUND:
171 return "ALIGN_COMPOUND";
172 case BFCR_STATE_READ_BASIC_BEGIN:
173 return "READ_BASIC_BEGIN";
174 case BFCR_STATE_READ_BASIC_CONTINUE:
175 return "READ_BASIC_CONTINUE";
176 case BFCR_STATE_DONE:
177 return "DONE";
178 }
179
180 bt_common_abort();
5cd6d0e5
PP
181}
182
4164020e 183static struct stack *stack_new(struct bt_bfcr *bfcr)
5cd6d0e5 184{
4164020e 185 struct stack *stack = NULL;
5cd6d0e5 186
4164020e
SM
187 stack = g_new0(struct stack, 1);
188 if (!stack) {
189 BT_COMP_LOGE_STR("Failed to allocate one stack.");
190 goto error;
191 }
5cd6d0e5 192
4164020e
SM
193 stack->bfcr = bfcr;
194 stack->entries = g_array_new(FALSE, TRUE, sizeof(struct stack_entry));
195 if (!stack->entries) {
196 BT_COMP_LOGE_STR("Failed to allocate a GArray.");
197 goto error;
198 }
5cd6d0e5 199
4164020e
SM
200 BT_COMP_LOGD("Created stack: addr=%p", stack);
201 return stack;
5cd6d0e5
PP
202
203error:
4164020e
SM
204 g_free(stack);
205 return NULL;
5cd6d0e5
PP
206}
207
4164020e 208static void stack_destroy(struct stack *stack)
5cd6d0e5 209{
4164020e 210 struct bt_bfcr *bfcr;
80870e64 211
4164020e
SM
212 if (!stack) {
213 return;
214 }
5cd6d0e5 215
4164020e
SM
216 bfcr = stack->bfcr;
217 BT_COMP_LOGD("Destroying stack: addr=%p", stack);
5cd6d0e5 218
4164020e
SM
219 if (stack->entries) {
220 g_array_free(stack->entries, TRUE);
221 }
5cd6d0e5 222
4164020e 223 g_free(stack);
5cd6d0e5
PP
224}
225
4164020e 226static int stack_push(struct stack *stack, struct ctf_field_class *base_class, size_t base_len)
5cd6d0e5 227{
4164020e
SM
228 struct stack_entry *entry;
229 struct bt_bfcr *bfcr;
230
231 BT_ASSERT_DBG(stack);
232 BT_ASSERT_DBG(base_class);
233 bfcr = stack->bfcr;
234 BT_COMP_LOGT("Pushing field class on stack: stack-addr=%p, "
235 "fc-addr=%p, fc-type=%d, base-length=%zu, "
236 "stack-size-before=%zu, stack-size-after=%zu",
237 stack, base_class, base_class->type, base_len, stack->size, stack->size + 1);
238
239 if (stack->entries->len == stack->size) {
240 g_array_set_size(stack->entries, stack->size + 1);
241 }
242
d50d46f3 243 entry = &bt_g_array_index(stack->entries, struct stack_entry, stack->size);
4164020e
SM
244 entry->base_class = base_class;
245 entry->base_len = base_len;
246 entry->index = 0;
247 stack->size++;
248 return 0;
5cd6d0e5
PP
249}
250
4164020e
SM
251static inline int64_t get_compound_field_class_length(struct bt_bfcr *bfcr,
252 struct ctf_field_class *fc)
5cd6d0e5 253{
4164020e
SM
254 int64_t length;
255
256 switch (fc->type) {
257 case CTF_FIELD_CLASS_TYPE_STRUCT:
258 {
259 ctf_field_class_struct *struct_fc = ctf_field_class_as_struct(fc);
260
261 length = (int64_t) struct_fc->members->len;
262 break;
263 }
264 case CTF_FIELD_CLASS_TYPE_VARIANT:
265 {
266 /* Variant field classes always "contain" a single class */
267 length = 1;
268 break;
269 }
270 case CTF_FIELD_CLASS_TYPE_ARRAY:
271 {
272 struct ctf_field_class_array *array_fc = ctf_field_class_as_array(fc);
273
274 length = (int64_t) array_fc->length;
275 break;
276 }
277 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
278 length = bfcr->user.cbs.query.get_sequence_length(fc, bfcr->user.data);
279 break;
280 default:
281 bt_common_abort();
282 }
283
284 return length;
5cd6d0e5
PP
285}
286
4164020e 287static int stack_push_with_len(struct bt_bfcr *bfcr, struct ctf_field_class *base_class)
5cd6d0e5 288{
4164020e
SM
289 int ret;
290 int64_t length = get_compound_field_class_length(bfcr, base_class);
5cd6d0e5 291
4164020e
SM
292 if (length < 0) {
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;
297 goto end;
298 }
5cd6d0e5 299
4164020e 300 ret = stack_push(bfcr->stack, base_class, (size_t) length);
5cd6d0e5
PP
301
302end:
4164020e 303 return ret;
5cd6d0e5
PP
304}
305
4164020e 306static inline unsigned int stack_size(struct stack *stack)
5cd6d0e5 307{
4164020e
SM
308 BT_ASSERT_DBG(stack);
309 return stack->size;
5cd6d0e5
PP
310}
311
4164020e 312static void stack_pop(struct stack *stack)
5cd6d0e5 313{
4164020e
SM
314 struct bt_bfcr *bfcr;
315
316 BT_ASSERT_DBG(stack);
317 BT_ASSERT_DBG(stack_size(stack));
318 bfcr = stack->bfcr;
319 BT_COMP_LOGT("Popping from stack: "
320 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
321 stack, stack->entries->len, stack->entries->len - 1);
322 stack->size--;
5cd6d0e5
PP
323}
324
4164020e 325static inline bool stack_empty(struct stack *stack)
5cd6d0e5 326{
4164020e 327 return stack_size(stack) == 0;
5cd6d0e5
PP
328}
329
4164020e 330static void stack_clear(struct stack *stack)
5cd6d0e5 331{
4164020e
SM
332 BT_ASSERT_DBG(stack);
333 stack->size = 0;
5cd6d0e5
PP
334}
335
4164020e 336static inline struct stack_entry *stack_top(struct stack *stack)
5cd6d0e5 337{
4164020e
SM
338 BT_ASSERT_DBG(stack);
339 BT_ASSERT_DBG(stack_size(stack));
d50d46f3 340 return &bt_g_array_index(stack->entries, struct stack_entry, stack->size - 1);
5cd6d0e5
PP
341}
342
4164020e 343static inline size_t available_bits(struct bt_bfcr *bfcr)
5cd6d0e5 344{
4164020e 345 return bfcr->buf.sz - bfcr->buf.at;
5cd6d0e5
PP
346}
347
4164020e 348static inline void consume_bits(struct bt_bfcr *bfcr, size_t incr)
5cd6d0e5 349{
4164020e
SM
350 BT_COMP_LOGT("Advancing cursor: bfcr-addr=%p, cur-before=%zu, cur-after=%zu", bfcr,
351 bfcr->buf.at, bfcr->buf.at + incr);
352 bfcr->buf.at += incr;
5cd6d0e5
PP
353}
354
4164020e 355static inline bool has_enough_bits(struct bt_bfcr *bfcr, size_t sz)
5cd6d0e5 356{
4164020e 357 return available_bits(bfcr) >= sz;
5cd6d0e5
PP
358}
359
4164020e 360static inline bool at_least_one_bit_left(struct bt_bfcr *bfcr)
5cd6d0e5 361{
4164020e 362 return has_enough_bits(bfcr, 1);
5cd6d0e5
PP
363}
364
4164020e 365static inline size_t packet_at(struct bt_bfcr *bfcr)
5cd6d0e5 366{
4164020e 367 return bfcr->buf.packet_offset + bfcr->buf.at;
5cd6d0e5
PP
368}
369
4164020e 370static inline size_t buf_at_from_addr(struct bt_bfcr *bfcr)
5cd6d0e5 371{
4164020e
SM
372 /*
373 * Considering this:
374 *
375 * ====== offset ===== (17)
376 *
377 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
378 * ^
379 * addr (0) ==== at ==== (12)
380 *
381 * We want this:
382 *
383 * =============================== (29)
384 */
385 return bfcr->buf.offset + bfcr->buf.at;
5cd6d0e5
PP
386}
387
4164020e 388static void stitch_reset(struct bt_bfcr *bfcr)
5cd6d0e5 389{
4164020e
SM
390 bfcr->stitch.offset = 0;
391 bfcr->stitch.at = 0;
5cd6d0e5
PP
392}
393
4164020e 394static inline size_t stitch_at_from_addr(struct bt_bfcr *bfcr)
5cd6d0e5 395{
4164020e 396 return bfcr->stitch.offset + bfcr->stitch.at;
5cd6d0e5
PP
397}
398
4164020e 399static void stitch_append_from_buf(struct bt_bfcr *bfcr, size_t sz)
5cd6d0e5 400{
4164020e
SM
401 size_t stitch_byte_at;
402 size_t buf_byte_at;
403 size_t nb_bytes;
404
405 if (sz == 0) {
406 return;
407 }
408
409 stitch_byte_at = BITS_TO_BYTES_FLOOR(stitch_at_from_addr(bfcr));
410 buf_byte_at = BITS_TO_BYTES_FLOOR(buf_at_from_addr(bfcr));
411 nb_bytes = BITS_TO_BYTES_CEIL(sz);
412 BT_ASSERT(nb_bytes > 0);
413 BT_ASSERT(bfcr->buf.addr);
414 memcpy(&bfcr->stitch.buf[stitch_byte_at], &bfcr->buf.addr[buf_byte_at], nb_bytes);
415 bfcr->stitch.at += sz;
416 consume_bits(bfcr, sz);
5cd6d0e5
PP
417}
418
4164020e 419static void stitch_append_from_remaining_buf(struct bt_bfcr *bfcr)
5cd6d0e5 420{
4164020e 421 stitch_append_from_buf(bfcr, available_bits(bfcr));
5cd6d0e5
PP
422}
423
4164020e 424static void stitch_set_from_remaining_buf(struct bt_bfcr *bfcr)
5cd6d0e5 425{
4164020e
SM
426 stitch_reset(bfcr);
427 bfcr->stitch.offset = IN_BYTE_OFFSET(buf_at_from_addr(bfcr));
428 stitch_append_from_remaining_buf(bfcr);
5cd6d0e5
PP
429}
430
4164020e
SM
431static inline void read_unsigned_bitfield(struct bt_bfcr *bfcr, const uint8_t *buf, size_t at,
432 unsigned int field_size, enum ctf_byte_order bo,
433 uint64_t *v)
5cd6d0e5 434{
4164020e
SM
435 switch (bo) {
436 case CTF_BYTE_ORDER_BIG:
437 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
438 break;
439 case CTF_BYTE_ORDER_LITTLE:
440 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
441 break;
442 default:
443 bt_common_abort();
444 }
445
446 BT_COMP_LOGT("Read unsigned bit array: cur=%zu, size=%u, "
447 "bo=%d, val=%" PRIu64,
448 at, field_size, bo, *v);
5cd6d0e5
PP
449}
450
4164020e
SM
451static inline void read_signed_bitfield(struct bt_bfcr *bfcr, const uint8_t *buf, size_t at,
452 unsigned int field_size, enum ctf_byte_order bo, int64_t *v)
5cd6d0e5 453{
4164020e
SM
454 switch (bo) {
455 case CTF_BYTE_ORDER_BIG:
456 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
457 break;
458 case CTF_BYTE_ORDER_LITTLE:
459 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
460 break;
461 default:
462 bt_common_abort();
463 }
464
465 BT_COMP_LOGT("Read signed bit array: cur=%zu, size=%u, "
466 "bo=%d, val=%" PRId64,
467 at, field_size, bo, *v);
5cd6d0e5
PP
468}
469
4164020e 470typedef enum bt_bfcr_status (*read_basic_and_call_cb_t)(struct bt_bfcr *, const uint8_t *, size_t);
5cd6d0e5 471
4164020e
SM
472static inline enum bt_bfcr_status validate_contiguous_bo(struct bt_bfcr *bfcr,
473 enum ctf_byte_order next_bo)
5cd6d0e5 474{
4164020e
SM
475 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
476
477 /* Always valid when at a byte boundary */
478 if (packet_at(bfcr) % 8 == 0) {
479 goto end;
480 }
481
482 /* Always valid if last byte order is unknown */
483 if (bfcr->last_bo == CTF_BYTE_ORDER_UNKNOWN) {
484 goto end;
485 }
486
487 /* Always valid if next byte order is unknown */
488 if (next_bo == CTF_BYTE_ORDER_UNKNOWN) {
489 goto end;
490 }
491
492 /* Make sure last byte order is compatible with the next byte order */
493 switch (bfcr->last_bo) {
494 case CTF_BYTE_ORDER_BIG:
495 if (next_bo != CTF_BYTE_ORDER_BIG) {
496 status = BT_BFCR_STATUS_ERROR;
497 }
498 break;
499 case CTF_BYTE_ORDER_LITTLE:
500 if (next_bo != CTF_BYTE_ORDER_LITTLE) {
501 status = BT_BFCR_STATUS_ERROR;
502 }
503 break;
504 default:
505 status = BT_BFCR_STATUS_ERROR;
506 }
5cd6d0e5
PP
507
508end:
4164020e
SM
509 if (status < 0) {
510 BT_COMP_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
511 "bfcr-addr=%p, last-bo=%d, next-bo=%d",
512 bfcr, bfcr->last_bo, next_bo);
513 }
5cd6d0e5 514
4164020e 515 return status;
5cd6d0e5
PP
516}
517
4164020e
SM
518static enum bt_bfcr_status read_basic_float_and_call_cb(struct bt_bfcr *bfcr, const uint8_t *buf,
519 size_t at)
5cd6d0e5 520{
4164020e
SM
521 double dblval;
522 unsigned int field_size;
523 enum ctf_byte_order bo;
524 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
525 ctf_field_class_float *fc = ctf_field_class_as_float(bfcr->cur_basic_field_class);
526
527 BT_ASSERT_DBG(fc);
528 field_size = fc->base.size;
529 bo = fc->base.byte_order;
530 bfcr->cur_bo = bo;
531
532 switch (field_size) {
533 case 32:
534 {
535 uint64_t v;
536 union
537 {
538 uint32_t u;
539 float f;
540 } f32;
541
542 read_unsigned_bitfield(bfcr, buf, at, field_size, bo, &v);
543 f32.u = (uint32_t) v;
544 dblval = (double) f32.f;
545 break;
546 }
547 case 64:
548 {
549 union
550 {
551 uint64_t u;
552 double d;
553 } f64;
554
555 read_unsigned_bitfield(bfcr, buf, at, field_size, bo, &f64.u);
556 dblval = f64.d;
557 break;
558 }
559 default:
560 /* Only 32-bit and 64-bit fields are supported currently */
561 bt_common_abort();
562 }
563
564 BT_COMP_LOGT("Read floating point number value: bfcr=%p, cur=%zu, val=%f", bfcr, at, dblval);
565
566 if (bfcr->user.cbs.classes.floating_point) {
567 BT_COMP_LOGT("Calling user function (floating point number).");
568 status = bfcr->user.cbs.classes.floating_point(dblval, bfcr->cur_basic_field_class,
569 bfcr->user.data);
570 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(status));
571 if (status != BT_BFCR_STATUS_OK) {
572 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s", bfcr,
573 bt_bfcr_status_string(status));
574 }
575 }
576
577 return status;
5cd6d0e5
PP
578}
579
4164020e
SM
580static inline enum bt_bfcr_status read_basic_int_and_call_cb(struct bt_bfcr *bfcr,
581 const uint8_t *buf, size_t at)
5cd6d0e5 582{
4164020e
SM
583 unsigned int field_size;
584 enum ctf_byte_order bo;
585 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
586 ctf_field_class_int *fc = ctf_field_class_as_int(bfcr->cur_basic_field_class);
587
588 field_size = fc->base.size;
589 bo = fc->base.byte_order;
590
591 /*
592 * Update current byte order now because we could be reading
593 * the integer value of an enumeration class, and thus we know
594 * here the actual supporting integer class's byte order.
595 */
596 bfcr->cur_bo = bo;
597
598 if (fc->is_signed) {
599 int64_t v;
600
601 read_signed_bitfield(bfcr, buf, at, field_size, bo, &v);
602
603 if (bfcr->user.cbs.classes.signed_int) {
604 BT_COMP_LOGT("Calling user function (signed integer).");
605 status =
606 bfcr->user.cbs.classes.signed_int(v, bfcr->cur_basic_field_class, bfcr->user.data);
607 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(status));
608 if (status != BT_BFCR_STATUS_OK) {
609 BT_COMP_LOGW("User function failed: "
610 "bfcr-addr=%p, status=%s",
611 bfcr, bt_bfcr_status_string(status));
612 }
613 }
614 } else {
615 uint64_t v;
616
617 read_unsigned_bitfield(bfcr, buf, at, field_size, bo, &v);
618
619 if (bfcr->user.cbs.classes.unsigned_int) {
620 BT_COMP_LOGT("Calling user function (unsigned integer).");
621 status = bfcr->user.cbs.classes.unsigned_int(v, bfcr->cur_basic_field_class,
622 bfcr->user.data);
623 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(status));
624 if (status != BT_BFCR_STATUS_OK) {
625 BT_COMP_LOGW("User function failed: "
626 "bfcr-addr=%p, status=%s",
627 bfcr, bt_bfcr_status_string(status));
628 }
629 }
630 }
631
632 return status;
5cd6d0e5
PP
633}
634
4164020e
SM
635static inline enum bt_bfcr_status
636read_bit_array_class_and_call_continue(struct bt_bfcr *bfcr,
637 read_basic_and_call_cb_t read_basic_and_call_cb)
5cd6d0e5 638{
4164020e
SM
639 size_t available;
640 size_t needed_bits;
641 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
642 ctf_field_class_bit_array *fc = ctf_field_class_as_bit_array(bfcr->cur_basic_field_class);
643
644 if (!at_least_one_bit_left(bfcr)) {
645 BT_COMP_LOGT("Reached end of data: bfcr-addr=%p", bfcr);
646 status = BT_BFCR_STATUS_EOF;
647 goto end;
648 }
649
650 available = available_bits(bfcr);
651 needed_bits = fc->size - bfcr->stitch.at;
652 BT_COMP_LOGT("Continuing basic field decoding: "
653 "bfcr-addr=%p, field-size=%u, needed-size=%zu, "
654 "available-size=%zu",
655 bfcr, fc->size, needed_bits, available);
656 if (needed_bits <= available) {
657 /* We have all the bits; append to stitch, then decode */
658 stitch_append_from_buf(bfcr, needed_bits);
659 status = read_basic_and_call_cb(bfcr, bfcr->stitch.buf, bfcr->stitch.offset);
660 if (status != BT_BFCR_STATUS_OK) {
661 BT_COMP_LOGW("Cannot read basic field: "
662 "bfcr-addr=%p, fc-addr=%p, status=%s",
663 bfcr, bfcr->cur_basic_field_class, bt_bfcr_status_string(status));
664 goto end;
665 }
666
667 if (stack_empty(bfcr->stack)) {
668 /* Root is a basic class */
669 bfcr->state = BFCR_STATE_DONE;
670 } else {
671 /* Go to next field */
672 stack_top(bfcr->stack)->index++;
673 bfcr->state = BFCR_STATE_NEXT_FIELD;
674 bfcr->last_bo = bfcr->cur_bo;
675 }
676 goto end;
677 }
678
679 /* We are here; it means we don't have enough data to decode this */
680 BT_COMP_LOGT_STR("Not enough data to read the next basic field: appending to stitch buffer.");
681 stitch_append_from_remaining_buf(bfcr);
682 status = BT_BFCR_STATUS_EOF;
5cd6d0e5
PP
683
684end:
4164020e 685 return status;
5cd6d0e5
PP
686}
687
4164020e
SM
688static inline enum bt_bfcr_status
689read_bit_array_class_and_call_begin(struct bt_bfcr *bfcr,
690 read_basic_and_call_cb_t read_basic_and_call_cb)
5cd6d0e5 691{
4164020e
SM
692 size_t available;
693 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
694 ctf_field_class_bit_array *fc = ctf_field_class_as_bit_array(bfcr->cur_basic_field_class);
695
696 if (!at_least_one_bit_left(bfcr)) {
697 BT_COMP_LOGT("Reached end of data: bfcr-addr=%p", bfcr);
698 status = BT_BFCR_STATUS_EOF;
699 goto end;
700 }
701
702 status = validate_contiguous_bo(bfcr, fc->byte_order);
703 if (status != BT_BFCR_STATUS_OK) {
704 /* validate_contiguous_bo() logs errors */
705 goto end;
706 }
707
708 available = available_bits(bfcr);
709
710 if (fc->size <= available) {
711 /* We have all the bits; decode and set now */
712 BT_ASSERT_DBG(bfcr->buf.addr);
713 status = read_basic_and_call_cb(bfcr, bfcr->buf.addr, buf_at_from_addr(bfcr));
714 if (status != BT_BFCR_STATUS_OK) {
715 BT_COMP_LOGW("Cannot read basic field: "
716 "bfcr-addr=%p, fc-addr=%p, status=%s",
717 bfcr, bfcr->cur_basic_field_class, bt_bfcr_status_string(status));
718 goto end;
719 }
720
721 consume_bits(bfcr, fc->size);
722
723 if (stack_empty(bfcr->stack)) {
724 /* Root is a basic class */
725 bfcr->state = BFCR_STATE_DONE;
726 } else {
727 /* Go to next field */
728 stack_top(bfcr->stack)->index++;
729 bfcr->state = BFCR_STATE_NEXT_FIELD;
730 bfcr->last_bo = bfcr->cur_bo;
731 }
732
733 goto end;
734 }
735
736 /* We are here; it means we don't have enough data to decode this */
737 BT_COMP_LOGT_STR("Not enough data to read the next basic field: setting stitch buffer.");
738 stitch_set_from_remaining_buf(bfcr);
739 bfcr->state = BFCR_STATE_READ_BASIC_CONTINUE;
740 status = BT_BFCR_STATUS_EOF;
5cd6d0e5
PP
741
742end:
4164020e 743 return status;
5cd6d0e5
PP
744}
745
4164020e 746static inline enum bt_bfcr_status read_basic_int_class_and_call_begin(struct bt_bfcr *bfcr)
5cd6d0e5 747{
4164020e 748 return read_bit_array_class_and_call_begin(bfcr, read_basic_int_and_call_cb);
5cd6d0e5
PP
749}
750
4164020e 751static inline enum bt_bfcr_status read_basic_int_class_and_call_continue(struct bt_bfcr *bfcr)
5cd6d0e5 752{
4164020e 753 return read_bit_array_class_and_call_continue(bfcr, read_basic_int_and_call_cb);
5cd6d0e5
PP
754}
755
4164020e 756static inline enum bt_bfcr_status read_basic_float_class_and_call_begin(struct bt_bfcr *bfcr)
5cd6d0e5 757{
4164020e 758 return read_bit_array_class_and_call_begin(bfcr, read_basic_float_and_call_cb);
5cd6d0e5
PP
759}
760
4164020e 761static inline enum bt_bfcr_status read_basic_float_class_and_call_continue(struct bt_bfcr *bfcr)
5cd6d0e5 762{
4164020e 763 return read_bit_array_class_and_call_continue(bfcr, read_basic_float_and_call_cb);
5cd6d0e5
PP
764}
765
4164020e 766static inline enum bt_bfcr_status read_basic_string_class_and_call(struct bt_bfcr *bfcr, bool begin)
5cd6d0e5 767{
4164020e
SM
768 size_t buf_at_bytes;
769 const uint8_t *result;
770 size_t available_bytes;
771 const uint8_t *first_chr;
772 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
773
774 if (!at_least_one_bit_left(bfcr)) {
775 BT_COMP_LOGT("Reached end of data: bfcr-addr=%p", bfcr);
776 status = BT_BFCR_STATUS_EOF;
777 goto end;
778 }
779
780 BT_ASSERT_DBG(buf_at_from_addr(bfcr) % 8 == 0);
781 available_bytes = BITS_TO_BYTES_FLOOR(available_bits(bfcr));
782 buf_at_bytes = BITS_TO_BYTES_FLOOR(buf_at_from_addr(bfcr));
783 BT_ASSERT_DBG(bfcr->buf.addr);
784 first_chr = &bfcr->buf.addr[buf_at_bytes];
785 result = (const uint8_t *) memchr(first_chr, '\0', available_bytes);
786
787 if (begin && bfcr->user.cbs.classes.string_begin) {
788 BT_COMP_LOGT("Calling user function (string, beginning).");
789 status = bfcr->user.cbs.classes.string_begin(bfcr->cur_basic_field_class, bfcr->user.data);
790 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(status));
791 if (status != BT_BFCR_STATUS_OK) {
792 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s", bfcr,
793 bt_bfcr_status_string(status));
794 goto end;
795 }
796 }
797
798 if (!result) {
799 /* No null character yet */
800 if (bfcr->user.cbs.classes.string) {
801 BT_COMP_LOGT("Calling user function (substring).");
802 status = bfcr->user.cbs.classes.string((const char *) first_chr, available_bytes,
803 bfcr->cur_basic_field_class, bfcr->user.data);
804 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(status));
805 if (status != BT_BFCR_STATUS_OK) {
806 BT_COMP_LOGW("User function failed: "
807 "bfcr-addr=%p, status=%s",
808 bfcr, bt_bfcr_status_string(status));
809 goto end;
810 }
811 }
812
813 consume_bits(bfcr, BYTES_TO_BITS(available_bytes));
814 bfcr->state = BFCR_STATE_READ_BASIC_CONTINUE;
815 status = BT_BFCR_STATUS_EOF;
816 } else {
817 /* Found the null character */
818 size_t result_len = (size_t) (result - first_chr);
819
820 if (bfcr->user.cbs.classes.string && result_len) {
821 BT_COMP_LOGT("Calling user function (substring).");
822 status = bfcr->user.cbs.classes.string((const char *) first_chr, result_len,
823 bfcr->cur_basic_field_class, bfcr->user.data);
824 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(status));
825 if (status != BT_BFCR_STATUS_OK) {
826 BT_COMP_LOGW("User function failed: "
827 "bfcr-addr=%p, status=%s",
828 bfcr, bt_bfcr_status_string(status));
829 goto end;
830 }
831 }
832
833 if (bfcr->user.cbs.classes.string_end) {
834 BT_COMP_LOGT("Calling user function (string, end).");
835 status =
836 bfcr->user.cbs.classes.string_end(bfcr->cur_basic_field_class, bfcr->user.data);
837 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(status));
838 if (status != BT_BFCR_STATUS_OK) {
839 BT_COMP_LOGW("User function failed: "
840 "bfcr-addr=%p, status=%s",
841 bfcr, bt_bfcr_status_string(status));
842 goto end;
843 }
844 }
845
846 consume_bits(bfcr, BYTES_TO_BITS(result_len + 1));
847
848 if (stack_empty(bfcr->stack)) {
849 /* Root is a basic class */
850 bfcr->state = BFCR_STATE_DONE;
851 } else {
852 /* Go to next field */
853 stack_top(bfcr->stack)->index++;
854 bfcr->state = BFCR_STATE_NEXT_FIELD;
855 bfcr->last_bo = bfcr->cur_bo;
856 }
857 }
5cd6d0e5
PP
858
859end:
4164020e 860 return status;
5cd6d0e5
PP
861}
862
4164020e 863static inline enum bt_bfcr_status read_basic_begin_state(struct bt_bfcr *bfcr)
5cd6d0e5 864{
4164020e
SM
865 enum bt_bfcr_status status;
866
867 BT_ASSERT_DBG(bfcr->cur_basic_field_class);
868
869 switch (bfcr->cur_basic_field_class->type) {
870 case CTF_FIELD_CLASS_TYPE_INT:
871 case CTF_FIELD_CLASS_TYPE_ENUM:
872 status = read_basic_int_class_and_call_begin(bfcr);
873 break;
874 case CTF_FIELD_CLASS_TYPE_FLOAT:
875 status = read_basic_float_class_and_call_begin(bfcr);
876 break;
877 case CTF_FIELD_CLASS_TYPE_STRING:
878 status = read_basic_string_class_and_call(bfcr, true);
879 break;
880 default:
881 bt_common_abort();
882 }
883
884 return status;
5cd6d0e5
PP
885}
886
4164020e 887static inline enum bt_bfcr_status read_basic_continue_state(struct bt_bfcr *bfcr)
5cd6d0e5 888{
4164020e
SM
889 enum bt_bfcr_status status;
890
891 BT_ASSERT_DBG(bfcr->cur_basic_field_class);
892
893 switch (bfcr->cur_basic_field_class->type) {
894 case CTF_FIELD_CLASS_TYPE_INT:
895 case CTF_FIELD_CLASS_TYPE_ENUM:
896 status = read_basic_int_class_and_call_continue(bfcr);
897 break;
898 case CTF_FIELD_CLASS_TYPE_FLOAT:
899 status = read_basic_float_class_and_call_continue(bfcr);
900 break;
901 case CTF_FIELD_CLASS_TYPE_STRING:
902 status = read_basic_string_class_and_call(bfcr, false);
903 break;
904 default:
905 bt_common_abort();
906 }
907
908 return status;
5cd6d0e5
PP
909}
910
4164020e 911static inline size_t bits_to_skip_to_align_to(struct bt_bfcr *bfcr, size_t align)
5cd6d0e5 912{
4164020e 913 size_t aligned_packet_at;
5cd6d0e5 914
4164020e
SM
915 aligned_packet_at = BT_ALIGN(packet_at(bfcr), align);
916 return aligned_packet_at - packet_at(bfcr);
5cd6d0e5
PP
917}
918
4164020e
SM
919static inline enum bt_bfcr_status align_class_state(struct bt_bfcr *bfcr,
920 struct ctf_field_class *field_class,
921 enum bfcr_state next_state)
5cd6d0e5 922{
4164020e
SM
923 unsigned int field_alignment;
924 size_t skip_bits;
925 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
926
927 /* Get field's alignment */
928 field_alignment = field_class->alignment;
929
930 /*
931 * 0 means "undefined" for variants; what we really want is 1
932 * (always aligned)
933 */
934 BT_ASSERT_DBG(field_alignment >= 1);
935
936 /* Compute how many bits we need to skip */
937 skip_bits = bits_to_skip_to_align_to(bfcr, (size_t) field_alignment);
938
939 /* Nothing to skip? aligned */
940 if (skip_bits == 0) {
941 bfcr->state = next_state;
942 goto end;
943 }
944
945 /* Make sure there's at least one bit left */
946 if (!at_least_one_bit_left(bfcr)) {
947 status = BT_BFCR_STATUS_EOF;
948 goto end;
949 }
950
951 /* Consume as many bits as possible in what's left */
952 consume_bits(bfcr, MIN(available_bits(bfcr), skip_bits));
953
954 /* Are we done now? */
955 skip_bits = bits_to_skip_to_align_to(bfcr, field_alignment);
956 if (skip_bits == 0) {
957 /* Yes: go to next state */
958 bfcr->state = next_state;
959 goto end;
960 } else {
961 /* No: need more data */
962 BT_COMP_LOGT("Reached end of data when aligning: bfcr-addr=%p", bfcr);
963 status = BT_BFCR_STATUS_EOF;
964 }
5cd6d0e5
PP
965
966end:
4164020e 967 return status;
5cd6d0e5
PP
968}
969
4164020e 970static inline enum bt_bfcr_status next_field_state(struct bt_bfcr *bfcr)
5cd6d0e5 971{
4164020e
SM
972 int ret;
973 struct stack_entry *top;
974 struct ctf_field_class *next_field_class = NULL;
975 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
976
977 if (stack_empty(bfcr->stack)) {
978 goto end;
979 }
980
981 top = stack_top(bfcr->stack);
982
983 /* Are we done with this base class? */
984 while (top->index == top->base_len) {
985 if (bfcr->user.cbs.classes.compound_end) {
986 BT_COMP_LOGT("Calling user function (compound, end).");
987 status = bfcr->user.cbs.classes.compound_end(top->base_class, bfcr->user.data);
988 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(status));
989 if (status != BT_BFCR_STATUS_OK) {
990 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s", bfcr,
991 bt_bfcr_status_string(status));
992 goto end;
993 }
994 }
995
996 stack_pop(bfcr->stack);
997
998 /* Are we done with the root class? */
999 if (stack_empty(bfcr->stack)) {
1000 bfcr->state = BFCR_STATE_DONE;
1001 goto end;
1002 }
1003
1004 top = stack_top(bfcr->stack);
1005 top->index++;
1006 }
1007
1008 /* Get next field's class */
1009 switch (top->base_class->type) {
1010 case CTF_FIELD_CLASS_TYPE_STRUCT:
1011 next_field_class = ctf_field_class_struct_borrow_member_by_index(
1012 ctf_field_class_as_struct(top->base_class), (uint64_t) top->index)
1013 ->fc;
1014 break;
1015 case CTF_FIELD_CLASS_TYPE_ARRAY:
1016 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
1017 {
1018 ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(top->base_class);
1019
1020 next_field_class = array_fc->elem_fc;
1021 break;
1022 }
1023 case CTF_FIELD_CLASS_TYPE_VARIANT:
1024 /* Variant classes are dynamic: the user should know! */
1025 next_field_class = bfcr->user.cbs.query.borrow_variant_selected_field_class(
1026 top->base_class, bfcr->user.data);
1027 break;
1028 default:
1029 break;
1030 }
1031
1032 if (!next_field_class) {
1033 BT_COMP_LOGW("Cannot get the field class of the next field: "
1034 "bfcr-addr=%p, base-fc-addr=%p, base-fc-type=%d, "
1035 "index=%" PRId64,
1036 bfcr, top->base_class, top->base_class->type, top->index);
1037 status = BT_BFCR_STATUS_ERROR;
1038 goto end;
1039 }
1040
1041 if (next_field_class->is_compound) {
1042 if (bfcr->user.cbs.classes.compound_begin) {
1043 BT_COMP_LOGT("Calling user function (compound, begin).");
1044 status = bfcr->user.cbs.classes.compound_begin(next_field_class, bfcr->user.data);
1045 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(status));
1046 if (status != BT_BFCR_STATUS_OK) {
1047 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s", bfcr,
1048 bt_bfcr_status_string(status));
1049 goto end;
1050 }
1051 }
1052
1053 ret = stack_push_with_len(bfcr, next_field_class);
1054 if (ret) {
1055 /* stack_push_with_len() logs errors */
1056 status = BT_BFCR_STATUS_ERROR;
1057 goto end;
1058 }
1059
1060 /* Next state: align a compound class */
1061 bfcr->state = BFCR_STATE_ALIGN_COMPOUND;
1062 } else {
1063 /* Replace current basic field class */
1064 BT_COMP_LOGT("Replacing current basic field class: "
1065 "bfcr-addr=%p, cur-basic-fc-addr=%p, "
1066 "next-basic-fc-addr=%p",
1067 bfcr, bfcr->cur_basic_field_class, next_field_class);
1068 bfcr->cur_basic_field_class = next_field_class;
1069
1070 /* Next state: align a basic class */
1071 bfcr->state = BFCR_STATE_ALIGN_BASIC;
1072 }
5cd6d0e5
PP
1073
1074end:
4164020e 1075 return status;
5cd6d0e5
PP
1076}
1077
4164020e 1078static inline enum bt_bfcr_status handle_state(struct bt_bfcr *bfcr)
5cd6d0e5 1079{
4164020e
SM
1080 enum bt_bfcr_status status = BT_BFCR_STATUS_OK;
1081
1082 BT_COMP_LOGT("Handling state: bfcr-addr=%p, state=%s", bfcr, bfcr_state_string(bfcr->state));
1083
1084 switch (bfcr->state) {
1085 case BFCR_STATE_NEXT_FIELD:
1086 status = next_field_state(bfcr);
1087 break;
1088 case BFCR_STATE_ALIGN_BASIC:
1089 status = align_class_state(bfcr, bfcr->cur_basic_field_class, BFCR_STATE_READ_BASIC_BEGIN);
1090 break;
1091 case BFCR_STATE_ALIGN_COMPOUND:
1092 status = align_class_state(bfcr, stack_top(bfcr->stack)->base_class, BFCR_STATE_NEXT_FIELD);
1093 break;
1094 case BFCR_STATE_READ_BASIC_BEGIN:
1095 status = read_basic_begin_state(bfcr);
1096 break;
1097 case BFCR_STATE_READ_BASIC_CONTINUE:
1098 status = read_basic_continue_state(bfcr);
1099 break;
1100 case BFCR_STATE_DONE:
1101 break;
1102 }
1103
1104 BT_COMP_LOGT("Handled state: bfcr-addr=%p, status=%s", bfcr, bt_bfcr_status_string(status));
1105 return status;
5cd6d0e5
PP
1106}
1107
4164020e
SM
1108struct bt_bfcr *bt_bfcr_create(struct bt_bfcr_cbs cbs, void *data, bt_logging_level log_level,
1109 bt_self_component *self_comp)
5cd6d0e5 1110{
4164020e
SM
1111 struct bt_bfcr *bfcr;
1112
1113 BT_COMP_LOG_CUR_LVL(BT_LOG_DEBUG, log_level, self_comp,
1114 "Creating binary field class reader (BFCR).");
1115 bfcr = g_new0(struct bt_bfcr, 1);
1116 if (!bfcr) {
1117 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_comp,
1118 "Failed to allocate one binary class reader.");
1119 goto end;
1120 }
1121
1122 bfcr->log_level = log_level;
1123 bfcr->self_comp = self_comp;
1124 bfcr->stack = stack_new(bfcr);
1125 if (!bfcr->stack) {
1126 BT_COMP_LOGE_STR("Cannot create BFCR's stack.");
1127 bt_bfcr_destroy(bfcr);
1128 bfcr = NULL;
1129 goto end;
1130 }
1131
1132 bfcr->state = BFCR_STATE_NEXT_FIELD;
1133 bfcr->user.cbs = cbs;
1134 bfcr->user.data = data;
1135 BT_COMP_LOGD("Created BFCR: addr=%p", bfcr);
5cd6d0e5
PP
1136
1137end:
4164020e 1138 return bfcr;
5cd6d0e5
PP
1139}
1140
5cd6d0e5
PP
1141void bt_bfcr_destroy(struct bt_bfcr *bfcr)
1142{
4164020e
SM
1143 if (bfcr->stack) {
1144 stack_destroy(bfcr->stack);
1145 }
5cd6d0e5 1146
4164020e
SM
1147 BT_COMP_LOGD("Destroying BFCR: addr=%p", bfcr);
1148 g_free(bfcr);
5cd6d0e5
PP
1149}
1150
4164020e 1151static void reset(struct bt_bfcr *bfcr)
5cd6d0e5 1152{
4164020e
SM
1153 BT_COMP_LOGD("Resetting BFCR: addr=%p", bfcr);
1154 stack_clear(bfcr->stack);
1155 stitch_reset(bfcr);
1156 bfcr->buf.addr = NULL;
1157 bfcr->last_bo = CTF_BYTE_ORDER_UNKNOWN;
5cd6d0e5
PP
1158}
1159
4164020e 1160static void update_packet_offset(struct bt_bfcr *bfcr)
5cd6d0e5 1161{
4164020e
SM
1162 BT_COMP_LOGT("Updating packet offset for next call: "
1163 "bfcr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1164 bfcr, bfcr->buf.packet_offset, bfcr->buf.packet_offset + bfcr->buf.at);
1165 bfcr->buf.packet_offset += bfcr->buf.at;
5cd6d0e5
PP
1166}
1167
4164020e
SM
1168size_t bt_bfcr_start(struct bt_bfcr *bfcr, struct ctf_field_class *cls, const uint8_t *buf,
1169 size_t offset, size_t packet_offset, size_t sz, enum bt_bfcr_status *status)
5cd6d0e5 1170{
4164020e
SM
1171 BT_ASSERT_DBG(bfcr);
1172 BT_ASSERT_DBG(BYTES_TO_BITS(sz) >= offset);
1173 reset(bfcr);
1174 bfcr->buf.addr = buf;
1175 bfcr->buf.offset = offset;
1176 bfcr->buf.at = 0;
1177 bfcr->buf.packet_offset = packet_offset;
1178 bfcr->buf.buf_sz = sz;
1179 bfcr->buf.sz = BYTES_TO_BITS(sz) - offset;
1180 *status = BT_BFCR_STATUS_OK;
1181
1182 BT_COMP_LOGT("Starting decoding: bfcr-addr=%p, fc-addr=%p, "
1183 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1184 "packet-offset=%zu",
1185 bfcr, cls, buf, sz, offset, packet_offset);
1186
1187 /* Set root class */
1188 if (cls->is_compound) {
1189 /* Compound class: push on visit stack */
1190 int stack_ret;
1191
1192 if (bfcr->user.cbs.classes.compound_begin) {
1193 BT_COMP_LOGT("Calling user function (compound, begin).");
1194 *status = bfcr->user.cbs.classes.compound_begin(cls, bfcr->user.data);
1195 BT_COMP_LOGT("User function returned: status=%s", bt_bfcr_status_string(*status));
1196 if (*status != BT_BFCR_STATUS_OK) {
1197 BT_COMP_LOGW("User function failed: bfcr-addr=%p, status=%s", bfcr,
1198 bt_bfcr_status_string(*status));
1199 goto end;
1200 }
1201 }
1202
1203 stack_ret = stack_push_with_len(bfcr, cls);
1204 if (stack_ret) {
1205 /* stack_push_with_len() logs errors */
1206 *status = BT_BFCR_STATUS_ERROR;
1207 goto end;
1208 }
1209
1210 bfcr->state = BFCR_STATE_ALIGN_COMPOUND;
1211 } else {
1212 /* Basic class: set as current basic class */
1213 bfcr->cur_basic_field_class = cls;
1214 bfcr->state = BFCR_STATE_ALIGN_BASIC;
1215 }
1216
1217 /* Run the machine! */
1218 BT_COMP_LOGT_STR("Running the state machine.");
1219
1220 while (true) {
1221 *status = handle_state(bfcr);
1222 if (*status != BT_BFCR_STATUS_OK || bfcr->state == BFCR_STATE_DONE) {
1223 break;
1224 }
1225 }
1226
1227 /* Update packet offset for next time */
1228 update_packet_offset(bfcr);
5cd6d0e5
PP
1229
1230end:
4164020e 1231 return bfcr->buf.at;
5cd6d0e5
PP
1232}
1233
5cd6d0e5 1234size_t bt_bfcr_continue(struct bt_bfcr *bfcr, const uint8_t *buf, size_t sz,
4164020e 1235 enum bt_bfcr_status *status)
5cd6d0e5 1236{
4164020e
SM
1237 BT_ASSERT_DBG(bfcr);
1238 BT_ASSERT_DBG(buf);
1239 BT_ASSERT_DBG(sz > 0);
1240 bfcr->buf.addr = buf;
1241 bfcr->buf.offset = 0;
1242 bfcr->buf.at = 0;
1243 bfcr->buf.buf_sz = sz;
1244 bfcr->buf.sz = BYTES_TO_BITS(sz);
1245 *status = BT_BFCR_STATUS_OK;
1246
1247 BT_COMP_LOGT("Continuing decoding: bfcr-addr=%p, buf-addr=%p, buf-size=%zu", bfcr, buf, sz);
1248
1249 /* Continue running the machine */
1250 BT_COMP_LOGT_STR("Running the state machine.");
1251
1252 while (true) {
1253 *status = handle_state(bfcr);
1254 if (*status != BT_BFCR_STATUS_OK || bfcr->state == BFCR_STATE_DONE) {
1255 break;
1256 }
1257 }
1258
1259 /* Update packet offset for next time */
1260 update_packet_offset(bfcr);
1261 return bfcr->buf.at;
5cd6d0e5
PP
1262}
1263
4164020e 1264void bt_bfcr_set_unsigned_int_cb(struct bt_bfcr *bfcr, bt_bfcr_unsigned_int_cb_func cb)
5cd6d0e5 1265{
4164020e
SM
1266 BT_ASSERT_DBG(bfcr);
1267 BT_ASSERT_DBG(cb);
1268 bfcr->user.cbs.classes.unsigned_int = cb;
5cd6d0e5 1269}
This page took 0.133629 seconds and 4 git commands to generate.