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