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