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