Make API CTF-agnostic
[babeltrace.git] / plugins / ctf / common / btr / btr.c
CommitLineData
e98a2d6e
PP
1/*
2 * Babeltrace - CTF binary type reader (BTR)
3 *
4 * Copyright (c) 2015-2016 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
dfef8367 26#define BT_LOG_TAG "PLUGIN-CTF-BTR"
888d5a32 27#include "logging.h"
dfef8367 28
0fbb9a9f 29#include <stdlib.h>
e98a2d6e 30#include <stdint.h>
dfef8367 31#include <inttypes.h>
e98a2d6e
PP
32#include <stdio.h>
33#include <stddef.h>
34#include <stdbool.h>
f6ccaed9 35#include <babeltrace/assert-internal.h>
e98a2d6e 36#include <string.h>
3d9990ac 37#include <babeltrace/bitfield-internal.h>
3dca2276 38#include <babeltrace/common-internal.h>
9d408fca 39#include <babeltrace/babeltrace.h>
e98a2d6e 40#include <babeltrace/ref.h>
3d9990ac 41#include <babeltrace/align-internal.h>
e98a2d6e
PP
42#include <glib.h>
43
06a626b8 44#include "btr.h"
44c440bc 45#include "../metadata/ctf-meta.h"
e98a2d6e 46
e98a2d6e
PP
47#define DIV8(_x) ((_x) >> 3)
48#define BYTES_TO_BITS(_x) ((_x) * 8)
49#define BITS_TO_BYTES_FLOOR(_x) DIV8(_x)
50#define BITS_TO_BYTES_CEIL(_x) DIV8((_x) + 7)
51#define IN_BYTE_OFFSET(_at) ((_at) & 7)
52
53/* A visit stack entry */
54struct stack_entry {
55 /*
56 * Current type of base field, one of:
57 *
58 * * Structure
59 * * Array
60 * * Sequence
61 * * Variant
e98a2d6e 62 */
44c440bc 63 struct ctf_field_type *base_type;
e98a2d6e
PP
64
65 /* Length of base field (always 1 for variant types) */
66 int64_t base_len;
67
44c440bc 68 /* Index of next field to read */
e98a2d6e
PP
69 int64_t index;
70};
71
72/* Visit stack */
73struct stack {
4077d987
PP
74 /* Entries (struct stack_entry) */
75 GArray *entries;
76
77 /* Number of active entries */
78 size_t size;
e98a2d6e
PP
79};
80
81/* Reading states */
82enum btr_state {
83 BTR_STATE_NEXT_FIELD,
84 BTR_STATE_ALIGN_BASIC,
85 BTR_STATE_ALIGN_COMPOUND,
86 BTR_STATE_READ_BASIC_BEGIN,
87 BTR_STATE_READ_BASIC_CONTINUE,
88 BTR_STATE_DONE,
89};
90
91/* Binary type reader */
50842bdc 92struct bt_btr {
e98a2d6e
PP
93 /* Bisit stack */
94 struct stack *stack;
95
e98a2d6e 96 /* Current basic field type */
44c440bc 97 struct ctf_field_type *cur_basic_field_type;
e98a2d6e
PP
98
99 /* Current state */
100 enum btr_state state;
101
102 /*
103 * Last basic field type's byte order.
104 *
105 * This is used to detect errors since two contiguous basic
106 * types for which the common boundary is not the boundary of
107 * a byte cannot have different byte orders.
108 *
44c440bc
PP
109 * This is set to -1 on reset and when the last basic field type
110 * was a string type.
e98a2d6e 111 */
44c440bc 112 enum ctf_byte_order last_bo;
e98a2d6e
PP
113
114 /* Current byte order (copied to last_bo after a successful read) */
44c440bc 115 enum ctf_byte_order cur_bo;
e98a2d6e
PP
116
117 /* Stitch buffer infos */
118 struct {
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 /* 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 /* Callback functions */
50842bdc 153 struct bt_btr_cbs cbs;
e98a2d6e
PP
154
155 /* Private data */
156 void *data;
157 } user;
158};
159
dfef8367
PP
160static inline
161const char *btr_state_string(enum btr_state state)
162{
163 switch (state) {
164 case BTR_STATE_NEXT_FIELD:
165 return "BTR_STATE_NEXT_FIELD";
166 case BTR_STATE_ALIGN_BASIC:
167 return "BTR_STATE_ALIGN_BASIC";
168 case BTR_STATE_ALIGN_COMPOUND:
169 return "BTR_STATE_ALIGN_COMPOUND";
170 case BTR_STATE_READ_BASIC_BEGIN:
171 return "BTR_STATE_READ_BASIC_BEGIN";
172 case BTR_STATE_READ_BASIC_CONTINUE:
173 return "BTR_STATE_READ_BASIC_CONTINUE";
174 case BTR_STATE_DONE:
175 return "BTR_STATE_DONE";
176 default:
177 return "(unknown)";
178 }
179}
180
e98a2d6e
PP
181static
182struct stack *stack_new(void)
183{
184 struct stack *stack = NULL;
185
186 stack = g_new0(struct stack, 1);
187 if (!stack) {
dfef8367 188 BT_LOGE_STR("Failed to allocate one stack.");
e98a2d6e
PP
189 goto error;
190 }
191
4077d987 192 stack->entries = g_array_new(FALSE, TRUE, sizeof(struct stack_entry));
e98a2d6e 193 if (!stack->entries) {
4077d987 194 BT_LOGE_STR("Failed to allocate a GArray.");
e98a2d6e
PP
195 goto error;
196 }
197
dfef8367 198 BT_LOGD("Created stack: addr=%p", stack);
e98a2d6e
PP
199 return stack;
200
201error:
202 g_free(stack);
e98a2d6e
PP
203 return NULL;
204}
205
206static
207void stack_destroy(struct stack *stack)
208{
209 if (!stack) {
210 return;
211 }
212
dfef8367 213 BT_LOGD("Destroying stack: addr=%p", stack);
4077d987
PP
214
215 if (stack->entries) {
216 g_array_free(stack->entries, TRUE);
217 }
218
e98a2d6e
PP
219 g_free(stack);
220}
221
e98a2d6e 222static
44c440bc 223int stack_push(struct stack *stack, struct ctf_field_type *base_type,
e98a2d6e
PP
224 size_t base_len)
225{
e98a2d6e
PP
226 struct stack_entry *entry;
227
f6ccaed9
PP
228 BT_ASSERT(stack);
229 BT_ASSERT(base_type);
dfef8367 230 BT_LOGV("Pushing field type on stack: stack-addr=%p, "
44c440bc 231 "ft-addr=%p, ft-id=%d, base-length=%zu, "
4077d987 232 "stack-size-before=%zu, stack-size-after=%zu",
44c440bc 233 stack, base_type, base_type->id,
4077d987
PP
234 base_len, stack->size, stack->size + 1);
235
236 if (stack->entries->len == stack->size) {
237 g_array_set_size(stack->entries, stack->size + 1);
e98a2d6e
PP
238 }
239
4077d987 240 entry = &g_array_index(stack->entries, struct stack_entry, stack->size);
e98a2d6e 241 entry->base_type = base_type;
e98a2d6e 242 entry->base_len = base_len;
4077d987
PP
243 entry->index = 0;
244 stack->size++;
245 return 0;
e98a2d6e
PP
246}
247
44c440bc
PP
248static inline
249int64_t get_compound_field_type_length(struct bt_btr *btr,
250 struct ctf_field_type *ft)
251{
252 int64_t length;
253
254 switch (ft->id) {
255 case CTF_FIELD_TYPE_ID_STRUCT:
256 {
257 struct ctf_field_type_struct *struct_ft = (void *) ft;
258
259 length = (int64_t) struct_ft->members->len;
260 break;
261 }
262 case CTF_FIELD_TYPE_ID_VARIANT:
263 {
264 /* Variant field types always "contain" a single type */
265 length = 1;
266 break;
267 }
268 case CTF_FIELD_TYPE_ID_ARRAY:
269 {
270 struct ctf_field_type_array *array_ft = (void *) ft;
271
272 length = (int64_t) array_ft->length;
273 break;
274 }
275 case CTF_FIELD_TYPE_ID_SEQUENCE:
276 length = btr->user.cbs.query.get_sequence_length(ft,
277 btr->user.data);
278 break;
279 default:
280 abort();
281 }
282
283 return length;
284}
285
e98a2d6e 286static
44c440bc 287int stack_push_with_len(struct bt_btr *btr, struct ctf_field_type *base_type)
e98a2d6e 288{
44c440bc
PP
289 int ret;
290 int64_t length = get_compound_field_type_length(btr, base_type);
e98a2d6e 291
44c440bc 292 if (length < 0) {
dfef8367 293 BT_LOGW("Cannot get compound field type's field count: "
44c440bc
PP
294 "btr-addr=%p, ft-addr=%p, ft-id=%d",
295 btr, base_type, base_type->id);
50842bdc 296 ret = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
297 goto end;
298 }
299
44c440bc 300 ret = stack_push(btr->stack, base_type, (size_t) length);
e98a2d6e
PP
301
302end:
303 return ret;
304}
305
306static inline
307unsigned int stack_size(struct stack *stack)
308{
f6ccaed9 309 BT_ASSERT(stack);
4077d987 310 return stack->size;
e98a2d6e
PP
311}
312
313static
314void stack_pop(struct stack *stack)
315{
f6ccaed9
PP
316 BT_ASSERT(stack);
317 BT_ASSERT(stack_size(stack));
dfef8367
PP
318 BT_LOGV("Popping from stack: "
319 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
320 stack, stack->entries->len, stack->entries->len - 1);
4077d987 321 stack->size--;
e98a2d6e
PP
322}
323
324static inline
325bool stack_empty(struct stack *stack)
326{
327 return stack_size(stack) == 0;
328}
329
330static
331void stack_clear(struct stack *stack)
332{
f6ccaed9 333 BT_ASSERT(stack);
4077d987 334 stack->size = 0;
e98a2d6e
PP
335}
336
337static inline
338struct stack_entry *stack_top(struct stack *stack)
339{
f6ccaed9
PP
340 BT_ASSERT(stack);
341 BT_ASSERT(stack_size(stack));
4077d987
PP
342 return &g_array_index(stack->entries, struct stack_entry,
343 stack->size - 1);
e98a2d6e
PP
344}
345
346static inline
50842bdc 347size_t available_bits(struct bt_btr *btr)
e98a2d6e
PP
348{
349 return btr->buf.sz - btr->buf.at;
350}
351
352static inline
50842bdc 353void consume_bits(struct bt_btr *btr, size_t incr)
e98a2d6e 354{
dfef8367
PP
355 BT_LOGV("Advancing cursor: btr-addr=%p, cur-before=%zu, cur-after=%zu",
356 btr, btr->buf.at, btr->buf.at + incr);
e98a2d6e
PP
357 btr->buf.at += incr;
358}
359
360static inline
50842bdc 361bool has_enough_bits(struct bt_btr *btr, size_t sz)
e98a2d6e
PP
362{
363 return available_bits(btr) >= sz;
364}
365
366static inline
50842bdc 367bool at_least_one_bit_left(struct bt_btr *btr)
e98a2d6e
PP
368{
369 return has_enough_bits(btr, 1);
370}
371
372static inline
50842bdc 373size_t packet_at(struct bt_btr *btr)
e98a2d6e
PP
374{
375 return btr->buf.packet_offset + btr->buf.at;
376}
377
378static inline
50842bdc 379size_t buf_at_from_addr(struct bt_btr *btr)
e98a2d6e
PP
380{
381 /*
382 * Considering this:
383 *
384 * ====== offset ===== (17)
385 *
386 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
387 * ^
388 * addr (0) ==== at ==== (12)
389 *
390 * We want this:
391 *
392 * =============================== (29)
393 */
394 return btr->buf.offset + btr->buf.at;
395}
396
e98a2d6e 397static
50842bdc 398void stitch_reset(struct bt_btr *btr)
e98a2d6e
PP
399{
400 btr->stitch.offset = 0;
401 btr->stitch.at = 0;
402}
403
404static inline
50842bdc 405size_t stitch_at_from_addr(struct bt_btr *btr)
e98a2d6e
PP
406{
407 return btr->stitch.offset + btr->stitch.at;
408}
409
410static
50842bdc 411void stitch_append_from_buf(struct bt_btr *btr, size_t sz)
e98a2d6e
PP
412{
413 size_t stitch_byte_at;
414 size_t buf_byte_at;
5ae32b51 415 size_t nb_bytes;
e98a2d6e
PP
416
417 if (sz == 0) {
418 return;
419 }
420
421 stitch_byte_at =
422 BITS_TO_BYTES_FLOOR(stitch_at_from_addr(btr));
423 buf_byte_at = BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr));
424 nb_bytes = BITS_TO_BYTES_CEIL(sz);
f6ccaed9
PP
425 BT_ASSERT(nb_bytes > 0);
426 BT_ASSERT(btr->buf.addr);
e98a2d6e
PP
427 memcpy(&btr->stitch.buf[stitch_byte_at], &btr->buf.addr[buf_byte_at],
428 nb_bytes);
429 btr->stitch.at += sz;
430 consume_bits(btr, sz);
431}
432
433static
50842bdc 434void stitch_append_from_remaining_buf(struct bt_btr *btr)
e98a2d6e
PP
435{
436 stitch_append_from_buf(btr, available_bits(btr));
437}
438
439static
50842bdc 440void stitch_set_from_remaining_buf(struct bt_btr *btr)
e98a2d6e
PP
441{
442 stitch_reset(btr);
443 btr->stitch.offset = IN_BYTE_OFFSET(buf_at_from_addr(btr));
444 stitch_append_from_remaining_buf(btr);
445}
446
447static inline
44c440bc
PP
448void read_unsigned_bitfield(const uint8_t *buf, size_t at,
449 unsigned int field_size, enum ctf_byte_order bo,
450 uint64_t *v)
e98a2d6e 451{
e98a2d6e 452 switch (bo) {
44c440bc 453 case CTF_BYTE_ORDER_BIG:
e98a2d6e
PP
454 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
455 break;
44c440bc 456 case CTF_BYTE_ORDER_LITTLE:
e98a2d6e
PP
457 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
458 break;
459 default:
dfef8367 460 abort();
e98a2d6e
PP
461 }
462
44c440bc
PP
463 BT_LOGV("Read unsigned bit array: cur=%zu, size=%u, "
464 "bo=%d, val=%" PRIu64, at, field_size, bo, *v);
e98a2d6e
PP
465}
466
467static inline
44c440bc
PP
468void read_signed_bitfield(const uint8_t *buf, size_t at,
469 unsigned int field_size, enum ctf_byte_order bo, int64_t *v)
e98a2d6e 470{
e98a2d6e 471 switch (bo) {
44c440bc 472 case CTF_BYTE_ORDER_BIG:
e98a2d6e
PP
473 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
474 break;
44c440bc 475 case CTF_BYTE_ORDER_LITTLE:
e98a2d6e
PP
476 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
477 break;
478 default:
dfef8367 479 abort();
e98a2d6e
PP
480 }
481
44c440bc
PP
482 BT_LOGV("Read signed bit array: cur=%zu, size=%u, "
483 "bo=%d, val=%" PRId64, at, field_size, bo, *v);
e98a2d6e
PP
484}
485
50842bdc 486typedef enum bt_btr_status (* read_basic_and_call_cb_t)(struct bt_btr *,
dfef8367 487 const uint8_t *, size_t);
e98a2d6e
PP
488
489static inline
50842bdc 490enum bt_btr_status validate_contiguous_bo(struct bt_btr *btr,
44c440bc 491 enum ctf_byte_order next_bo)
e98a2d6e 492{
50842bdc 493 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
494
495 /* Always valid when at a byte boundary */
496 if (packet_at(btr) % 8 == 0) {
497 goto end;
498 }
499
500 /* Always valid if last byte order is unknown */
44c440bc 501 if (btr->last_bo == -1) {
e98a2d6e
PP
502 goto end;
503 }
504
505 /* Always valid if next byte order is unknown */
44c440bc 506 if (next_bo == -1) {
e98a2d6e
PP
507 goto end;
508 }
509
510 /* Make sure last byte order is compatible with the next byte order */
511 switch (btr->last_bo) {
44c440bc
PP
512 case CTF_BYTE_ORDER_BIG:
513 if (next_bo != CTF_BYTE_ORDER_BIG) {
50842bdc 514 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
515 }
516 break;
44c440bc
PP
517 case CTF_BYTE_ORDER_LITTLE:
518 if (next_bo != CTF_BYTE_ORDER_LITTLE) {
50842bdc 519 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
520 }
521 break;
522 default:
50842bdc 523 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
524 }
525
526end:
fdf0e7a0 527 if (status < 0) {
dfef8367 528 BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
44c440bc
PP
529 "btr-addr=%p, last-bo=%d, next-bo=%d",
530 btr, btr->last_bo, next_bo);
dfef8367
PP
531 }
532
e98a2d6e
PP
533 return status;
534}
535
536static
50842bdc 537enum bt_btr_status read_basic_float_and_call_cb(struct bt_btr *btr,
dfef8367 538 const uint8_t *buf, size_t at)
e98a2d6e 539{
e98a2d6e 540 double dblval;
44c440bc
PP
541 unsigned int field_size;
542 enum ctf_byte_order bo;
50842bdc 543 enum bt_btr_status status = BT_BTR_STATUS_OK;
44c440bc 544 struct ctf_field_type_float *ft = (void *) btr->cur_basic_field_type;
e98a2d6e 545
44c440bc
PP
546 BT_ASSERT(ft);
547 field_size = ft->base.size;
548 bo = ft->base.byte_order;
e98a2d6e
PP
549 btr->cur_bo = bo;
550
551 switch (field_size) {
552 case 32:
553 {
554 uint64_t v;
555 union {
556 uint32_t u;
557 float f;
558 } f32;
559
44c440bc 560 read_unsigned_bitfield(buf, at, field_size, bo, &v);
e98a2d6e
PP
561 f32.u = (uint32_t) v;
562 dblval = (double) f32.f;
563 break;
564 }
565 case 64:
566 {
567 union {
568 uint64_t u;
569 double d;
570 } f64;
571
44c440bc 572 read_unsigned_bitfield(buf, at, field_size, bo, &f64.u);
e98a2d6e
PP
573 dblval = f64.d;
574 break;
575 }
576 default:
577 /* Only 32-bit and 64-bit fields are supported currently */
44c440bc 578 abort();
e98a2d6e
PP
579 }
580
dfef8367
PP
581 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
582 btr, at, dblval);
583
e98a2d6e 584 if (btr->user.cbs.types.floating_point) {
dfef8367 585 BT_LOGV("Calling user function (floating point number).");
e98a2d6e
PP
586 status = btr->user.cbs.types.floating_point(dblval,
587 btr->cur_basic_field_type, btr->user.data);
dfef8367 588 BT_LOGV("User function returned: status=%s",
50842bdc
PP
589 bt_btr_status_string(status));
590 if (status != BT_BTR_STATUS_OK) {
dfef8367 591 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 592 btr, bt_btr_status_string(status));
dfef8367 593 }
e98a2d6e
PP
594 }
595
e98a2d6e
PP
596 return status;
597}
598
599static inline
44c440bc
PP
600enum bt_btr_status read_basic_int_and_call_cb(struct bt_btr *btr,
601 const uint8_t *buf, size_t at)
e98a2d6e 602{
44c440bc
PP
603 unsigned int field_size;
604 enum ctf_byte_order bo;
50842bdc 605 enum bt_btr_status status = BT_BTR_STATUS_OK;
44c440bc 606 struct ctf_field_type_int *ft = (void *) btr->cur_basic_field_type;
e98a2d6e 607
44c440bc
PP
608 field_size = ft->base.size;
609 bo = ft->base.byte_order;
e98a2d6e
PP
610
611 /*
612 * Update current byte order now because we could be reading
613 * the integer value of an enumeration type, and thus we know
614 * here the actual supporting integer type's byte order.
615 */
616 btr->cur_bo = bo;
617
44c440bc 618 if (ft->is_signed) {
e98a2d6e
PP
619 int64_t v;
620
44c440bc 621 read_signed_bitfield(buf, at, field_size, bo, &v);
e98a2d6e
PP
622
623 if (btr->user.cbs.types.signed_int) {
dfef8367 624 BT_LOGV("Calling user function (signed integer).");
e98a2d6e
PP
625 status = btr->user.cbs.types.signed_int(v,
626 btr->cur_basic_field_type, btr->user.data);
dfef8367 627 BT_LOGV("User function returned: status=%s",
50842bdc
PP
628 bt_btr_status_string(status));
629 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
630 BT_LOGW("User function failed: "
631 "btr-addr=%p, status=%s",
50842bdc 632 btr, bt_btr_status_string(status));
dfef8367 633 }
e98a2d6e
PP
634 }
635 } else {
636 uint64_t v;
637
44c440bc 638 read_unsigned_bitfield(buf, at, field_size, bo, &v);
e98a2d6e
PP
639
640 if (btr->user.cbs.types.unsigned_int) {
dfef8367 641 BT_LOGV("Calling user function (unsigned integer).");
e98a2d6e
PP
642 status = btr->user.cbs.types.unsigned_int(v,
643 btr->cur_basic_field_type, btr->user.data);
dfef8367 644 BT_LOGV("User function returned: status=%s",
50842bdc
PP
645 bt_btr_status_string(status));
646 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
647 BT_LOGW("User function failed: "
648 "btr-addr=%p, status=%s",
50842bdc 649 btr, bt_btr_status_string(status));
dfef8367 650 }
e98a2d6e
PP
651 }
652 }
653
e98a2d6e
PP
654 return status;
655}
656
657static inline
44c440bc 658enum bt_btr_status read_bit_array_type_and_call_continue(struct bt_btr *btr,
dfef8367 659 read_basic_and_call_cb_t read_basic_and_call_cb)
e98a2d6e
PP
660{
661 size_t available;
44c440bc 662 size_t needed_bits;
50842bdc 663 enum bt_btr_status status = BT_BTR_STATUS_OK;
44c440bc
PP
664 struct ctf_field_type_bit_array *ft =
665 (void *) btr->cur_basic_field_type;
e98a2d6e
PP
666
667 if (!at_least_one_bit_left(btr)) {
dfef8367 668 BT_LOGV("Reached end of data: btr-addr=%p", btr);
50842bdc 669 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
670 goto end;
671 }
672
e98a2d6e 673 available = available_bits(btr);
44c440bc 674 needed_bits = ft->size - btr->stitch.at;
dfef8367 675 BT_LOGV("Continuing basic field decoding: "
44c440bc 676 "btr-addr=%p, field-size=%u, needed-size=%" PRId64 ", "
dfef8367 677 "available-size=%zu",
44c440bc 678 btr, ft->size, needed_bits, available);
e98a2d6e
PP
679 if (needed_bits <= available) {
680 /* We have all the bits; append to stitch, then decode */
681 stitch_append_from_buf(btr, needed_bits);
682 status = read_basic_and_call_cb(btr, btr->stitch.buf,
683 btr->stitch.offset);
50842bdc 684 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
685 BT_LOGW("Cannot read basic field: "
686 "btr-addr=%p, ft-addr=%p, status=%s",
687 btr, btr->cur_basic_field_type,
50842bdc 688 bt_btr_status_string(status));
e98a2d6e
PP
689 goto end;
690 }
691
692 if (stack_empty(btr->stack)) {
693 /* Root is a basic type */
694 btr->state = BTR_STATE_DONE;
695 } else {
696 /* Go to next field */
697 stack_top(btr->stack)->index++;
698 btr->state = BTR_STATE_NEXT_FIELD;
699 btr->last_bo = btr->cur_bo;
700 }
701 goto end;
702 }
703
704 /* We are here; it means we don't have enough data to decode this */
dfef8367 705 BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer.");
e98a2d6e 706 stitch_append_from_remaining_buf(btr);
50842bdc 707 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
708
709end:
710 return status;
711}
712
713static inline
44c440bc 714enum bt_btr_status read_bit_array_type_and_call_begin(struct bt_btr *btr,
dfef8367 715 read_basic_and_call_cb_t read_basic_and_call_cb)
e98a2d6e
PP
716{
717 size_t available;
50842bdc 718 enum bt_btr_status status = BT_BTR_STATUS_OK;
44c440bc
PP
719 struct ctf_field_type_bit_array *ft =
720 (void *) btr->cur_basic_field_type;
e98a2d6e
PP
721
722 if (!at_least_one_bit_left(btr)) {
dfef8367 723 BT_LOGV("Reached end of data: btr-addr=%p", btr);
50842bdc 724 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
725 goto end;
726 }
727
44c440bc 728 status = validate_contiguous_bo(btr, ft->byte_order);
50842bdc 729 if (status != BT_BTR_STATUS_OK) {
dfef8367 730 /* validate_contiguous_bo() logs errors */
e98a2d6e
PP
731 goto end;
732 }
733
734 available = available_bits(btr);
735
44c440bc 736 if (ft->size <= available) {
e98a2d6e 737 /* We have all the bits; decode and set now */
f6ccaed9 738 BT_ASSERT(btr->buf.addr);
e98a2d6e
PP
739 status = read_basic_and_call_cb(btr, btr->buf.addr,
740 buf_at_from_addr(btr));
50842bdc 741 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
742 BT_LOGW("Cannot read basic field: "
743 "btr-addr=%p, ft-addr=%p, status=%s",
744 btr, btr->cur_basic_field_type,
50842bdc 745 bt_btr_status_string(status));
e98a2d6e
PP
746 goto end;
747 }
748
44c440bc 749 consume_bits(btr, ft->size);
e98a2d6e
PP
750
751 if (stack_empty(btr->stack)) {
752 /* Root is a basic type */
753 btr->state = BTR_STATE_DONE;
754 } else {
755 /* Go to next field */
756 stack_top(btr->stack)->index++;
757 btr->state = BTR_STATE_NEXT_FIELD;
758 btr->last_bo = btr->cur_bo;
759 }
760
761 goto end;
762 }
763
764 /* We are here; it means we don't have enough data to decode this */
dfef8367 765 BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer.");
e98a2d6e
PP
766 stitch_set_from_remaining_buf(btr);
767 btr->state = BTR_STATE_READ_BASIC_CONTINUE;
50842bdc 768 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
769
770end:
771 return status;
772}
773
774static inline
50842bdc
PP
775enum bt_btr_status read_basic_int_type_and_call_begin(
776 struct bt_btr *btr)
e98a2d6e 777{
44c440bc 778 return read_bit_array_type_and_call_begin(btr, read_basic_int_and_call_cb);
e98a2d6e
PP
779}
780
781static inline
50842bdc
PP
782enum bt_btr_status read_basic_int_type_and_call_continue(
783 struct bt_btr *btr)
e98a2d6e 784{
44c440bc 785 return read_bit_array_type_and_call_continue(btr,
e98a2d6e
PP
786 read_basic_int_and_call_cb);
787}
788
789static inline
50842bdc
PP
790enum bt_btr_status read_basic_float_type_and_call_begin(
791 struct bt_btr *btr)
e98a2d6e 792{
44c440bc 793 return read_bit_array_type_and_call_begin(btr,
e98a2d6e
PP
794 read_basic_float_and_call_cb);
795}
796
797static inline
50842bdc
PP
798enum bt_btr_status read_basic_float_type_and_call_continue(
799 struct bt_btr *btr)
e98a2d6e 800{
44c440bc 801 return read_bit_array_type_and_call_continue(btr,
e98a2d6e
PP
802 read_basic_float_and_call_cb);
803}
804
e98a2d6e 805static inline
50842bdc
PP
806enum bt_btr_status read_basic_string_type_and_call(
807 struct bt_btr *btr, bool begin)
e98a2d6e
PP
808{
809 size_t buf_at_bytes;
810 const uint8_t *result;
811 size_t available_bytes;
812 const uint8_t *first_chr;
50842bdc 813 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
814
815 if (!at_least_one_bit_left(btr)) {
dfef8367 816 BT_LOGV("Reached end of data: btr-addr=%p", btr);
50842bdc 817 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
818 goto end;
819 }
820
f6ccaed9 821 BT_ASSERT(buf_at_from_addr(btr) % 8 == 0);
e98a2d6e
PP
822 available_bytes = BITS_TO_BYTES_FLOOR(available_bits(btr));
823 buf_at_bytes = BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr));
f6ccaed9 824 BT_ASSERT(btr->buf.addr);
e98a2d6e
PP
825 first_chr = &btr->buf.addr[buf_at_bytes];
826 result = memchr(first_chr, '\0', available_bytes);
827
828 if (begin && btr->user.cbs.types.string_begin) {
dfef8367 829 BT_LOGV("Calling user function (string, beginning).");
e98a2d6e
PP
830 status = btr->user.cbs.types.string_begin(
831 btr->cur_basic_field_type, btr->user.data);
dfef8367 832 BT_LOGV("User function returned: status=%s",
50842bdc
PP
833 bt_btr_status_string(status));
834 if (status != BT_BTR_STATUS_OK) {
dfef8367 835 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 836 btr, bt_btr_status_string(status));
e98a2d6e
PP
837 goto end;
838 }
839 }
840
841 if (!result) {
842 /* No null character yet */
843 if (btr->user.cbs.types.string) {
dfef8367 844 BT_LOGV("Calling user function (substring).");
e98a2d6e
PP
845 status = btr->user.cbs.types.string(
846 (const char *) first_chr,
847 available_bytes, btr->cur_basic_field_type,
848 btr->user.data);
dfef8367 849 BT_LOGV("User function returned: status=%s",
50842bdc
PP
850 bt_btr_status_string(status));
851 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
852 BT_LOGW("User function failed: "
853 "btr-addr=%p, status=%s",
50842bdc 854 btr, bt_btr_status_string(status));
e98a2d6e
PP
855 goto end;
856 }
857 }
858
859 consume_bits(btr, BYTES_TO_BITS(available_bytes));
860 btr->state = BTR_STATE_READ_BASIC_CONTINUE;
50842bdc 861 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
862 } else {
863 /* Found the null character */
864 size_t result_len = (size_t) (result - first_chr);
865
866 if (btr->user.cbs.types.string && result_len) {
dfef8367 867 BT_LOGV("Calling user function (substring).");
e98a2d6e
PP
868 status = btr->user.cbs.types.string(
869 (const char *) first_chr,
870 result_len, btr->cur_basic_field_type,
871 btr->user.data);
dfef8367 872 BT_LOGV("User function returned: status=%s",
50842bdc
PP
873 bt_btr_status_string(status));
874 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
875 BT_LOGW("User function failed: "
876 "btr-addr=%p, status=%s",
50842bdc 877 btr, bt_btr_status_string(status));
e98a2d6e
PP
878 goto end;
879 }
880 }
881
882 if (btr->user.cbs.types.string_end) {
dfef8367 883 BT_LOGV("Calling user function (string, end).");
e98a2d6e
PP
884 status = btr->user.cbs.types.string_end(
885 btr->cur_basic_field_type, btr->user.data);
dfef8367 886 BT_LOGV("User function returned: status=%s",
50842bdc
PP
887 bt_btr_status_string(status));
888 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
889 BT_LOGW("User function failed: "
890 "btr-addr=%p, status=%s",
50842bdc 891 btr, bt_btr_status_string(status));
e98a2d6e
PP
892 goto end;
893 }
894 }
895
896 consume_bits(btr, BYTES_TO_BITS(result_len + 1));
897
898 if (stack_empty(btr->stack)) {
899 /* Root is a basic type */
900 btr->state = BTR_STATE_DONE;
901 } else {
902 /* Go to next field */
903 stack_top(btr->stack)->index++;
904 btr->state = BTR_STATE_NEXT_FIELD;
905 btr->last_bo = btr->cur_bo;
906 }
907 }
908
909end:
910 return status;
911}
912
913static inline
50842bdc 914enum bt_btr_status read_basic_begin_state(struct bt_btr *btr)
e98a2d6e 915{
50842bdc 916 enum bt_btr_status status;
e98a2d6e 917
f6ccaed9 918 BT_ASSERT(btr->cur_basic_field_type);
e98a2d6e 919
44c440bc
PP
920 switch (btr->cur_basic_field_type->id) {
921 case CTF_FIELD_TYPE_ID_INT:
922 case CTF_FIELD_TYPE_ID_ENUM:
e98a2d6e
PP
923 status = read_basic_int_type_and_call_begin(btr);
924 break;
44c440bc 925 case CTF_FIELD_TYPE_ID_FLOAT:
e98a2d6e
PP
926 status = read_basic_float_type_and_call_begin(btr);
927 break;
44c440bc 928 case CTF_FIELD_TYPE_ID_STRING:
e98a2d6e
PP
929 status = read_basic_string_type_and_call(btr, true);
930 break;
931 default:
0fbb9a9f 932 abort();
e98a2d6e
PP
933 }
934
935 return status;
936}
937
938static inline
50842bdc 939enum bt_btr_status read_basic_continue_state(struct bt_btr *btr)
e98a2d6e 940{
50842bdc 941 enum bt_btr_status status;
e98a2d6e 942
f6ccaed9 943 BT_ASSERT(btr->cur_basic_field_type);
e98a2d6e 944
44c440bc
PP
945 switch (btr->cur_basic_field_type->id) {
946 case CTF_FIELD_TYPE_ID_INT:
947 case CTF_FIELD_TYPE_ID_ENUM:
e98a2d6e
PP
948 status = read_basic_int_type_and_call_continue(btr);
949 break;
44c440bc 950 case CTF_FIELD_TYPE_ID_FLOAT:
e98a2d6e
PP
951 status = read_basic_float_type_and_call_continue(btr);
952 break;
44c440bc 953 case CTF_FIELD_TYPE_ID_STRING:
e98a2d6e
PP
954 status = read_basic_string_type_and_call(btr, false);
955 break;
956 default:
0fbb9a9f 957 abort();
e98a2d6e
PP
958 }
959
960 return status;
961}
962
963static inline
50842bdc 964size_t bits_to_skip_to_align_to(struct bt_btr *btr, size_t align)
e98a2d6e
PP
965{
966 size_t aligned_packet_at;
967
968 aligned_packet_at = ALIGN(packet_at(btr), align);
e98a2d6e
PP
969 return aligned_packet_at - packet_at(btr);
970}
971
972static inline
50842bdc 973enum bt_btr_status align_type_state(struct bt_btr *btr,
44c440bc 974 struct ctf_field_type *field_type, enum btr_state next_state)
e98a2d6e 975{
44c440bc 976 unsigned int field_alignment;
e98a2d6e 977 size_t skip_bits;
50842bdc 978 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
979
980 /* Get field's alignment */
44c440bc 981 field_alignment = field_type->alignment;
e98a2d6e
PP
982
983 /*
984 * 0 means "undefined" for variants; what we really want is 1
985 * (always aligned)
986 */
44c440bc 987 BT_ASSERT(field_alignment >= 1);
e98a2d6e
PP
988
989 /* Compute how many bits we need to skip */
44c440bc 990 skip_bits = bits_to_skip_to_align_to(btr, (size_t) field_alignment);
e98a2d6e
PP
991
992 /* Nothing to skip? aligned */
993 if (skip_bits == 0) {
994 btr->state = next_state;
995 goto end;
996 }
997
998 /* Make sure there's at least one bit left */
999 if (!at_least_one_bit_left(btr)) {
50842bdc 1000 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
1001 goto end;
1002 }
1003
1004 /* Consume as many bits as possible in what's left */
1005 consume_bits(btr, MIN(available_bits(btr), skip_bits));
1006
1007 /* Are we done now? */
1008 skip_bits = bits_to_skip_to_align_to(btr, field_alignment);
e98a2d6e
PP
1009 if (skip_bits == 0) {
1010 /* Yes: go to next state */
1011 btr->state = next_state;
1012 goto end;
1013 } else {
1014 /* No: need more data */
dfef8367 1015 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr);
50842bdc 1016 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
1017 }
1018
1019end:
1020 return status;
1021}
1022
e98a2d6e 1023static inline
50842bdc 1024enum bt_btr_status next_field_state(struct bt_btr *btr)
e98a2d6e
PP
1025{
1026 int ret;
1027 struct stack_entry *top;
44c440bc 1028 struct ctf_field_type *next_field_type = NULL;
50842bdc 1029 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
1030
1031 if (stack_empty(btr->stack)) {
1032 goto end;
1033 }
1034
1035 top = stack_top(btr->stack);
1036
1037 /* Are we done with this base type? */
1038 while (top->index == top->base_len) {
1039 if (btr->user.cbs.types.compound_end) {
dfef8367 1040 BT_LOGV("Calling user function (compound, end).");
e98a2d6e
PP
1041 status = btr->user.cbs.types.compound_end(
1042 top->base_type, btr->user.data);
dfef8367 1043 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1044 bt_btr_status_string(status));
1045 if (status != BT_BTR_STATUS_OK) {
dfef8367 1046 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 1047 btr, bt_btr_status_string(status));
e98a2d6e
PP
1048 goto end;
1049 }
1050 }
1051
1052 stack_pop(btr->stack);
1053
1054 /* Are we done with the root type? */
1055 if (stack_empty(btr->stack)) {
1056 btr->state = BTR_STATE_DONE;
1057 goto end;
1058 }
1059
1060 top = stack_top(btr->stack);
1061 top->index++;
1062 }
1063
1064 /* Get next field's type */
44c440bc
PP
1065 switch (top->base_type->id) {
1066 case CTF_FIELD_TYPE_ID_STRUCT:
1067 next_field_type = ctf_field_type_struct_borrow_member_by_index(
1068 (void *) top->base_type, (uint64_t) top->index)->ft;
e98a2d6e 1069 break;
44c440bc
PP
1070 case CTF_FIELD_TYPE_ID_ARRAY:
1071 case CTF_FIELD_TYPE_ID_SEQUENCE:
1072 {
1073 struct ctf_field_type_array_base *array_ft =
1074 (void *) top->base_type;
1075
1076 next_field_type = array_ft->elem_ft;
e98a2d6e 1077 break;
44c440bc
PP
1078 }
1079 case CTF_FIELD_TYPE_ID_VARIANT:
e98a2d6e
PP
1080 /* Variant types are dynamic: query the user, he should know! */
1081 next_field_type =
44c440bc 1082 btr->user.cbs.query.borrow_variant_selected_field_type(
e98a2d6e
PP
1083 top->base_type, btr->user.data);
1084 break;
1085 default:
1086 break;
1087 }
1088
1089 if (!next_field_type) {
dfef8367 1090 BT_LOGW("Cannot get the field type of the next field: "
44c440bc 1091 "btr-addr=%p, base-ft-addr=%p, base-ft-id=%d, "
dfef8367 1092 "index=%" PRId64,
44c440bc 1093 btr, top->base_type, top->base_type->id, top->index);
50842bdc 1094 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
1095 goto end;
1096 }
1097
44c440bc 1098 if (next_field_type->is_compound) {
e98a2d6e 1099 if (btr->user.cbs.types.compound_begin) {
dfef8367 1100 BT_LOGV("Calling user function (compound, begin).");
e98a2d6e
PP
1101 status = btr->user.cbs.types.compound_begin(
1102 next_field_type, btr->user.data);
dfef8367 1103 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1104 bt_btr_status_string(status));
1105 if (status != BT_BTR_STATUS_OK) {
dfef8367 1106 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 1107 btr, bt_btr_status_string(status));
e98a2d6e
PP
1108 goto end;
1109 }
1110 }
1111
1112 ret = stack_push_with_len(btr, next_field_type);
1113 if (ret) {
dfef8367 1114 /* stack_push_with_len() logs errors */
50842bdc 1115 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
1116 goto end;
1117 }
1118
1119 /* Next state: align a compound type */
1120 btr->state = BTR_STATE_ALIGN_COMPOUND;
1121 } else {
1122 /* Replace current basic field type */
dfef8367
PP
1123 BT_LOGV("Replacing current basic field type: "
1124 "btr-addr=%p, cur-basic-ft-addr=%p, "
1125 "next-basic-ft-addr=%p",
1126 btr, btr->cur_basic_field_type, next_field_type);
5ae32b51 1127 btr->cur_basic_field_type = next_field_type;
e98a2d6e
PP
1128
1129 /* Next state: align a basic type */
1130 btr->state = BTR_STATE_ALIGN_BASIC;
1131 }
1132
1133end:
e98a2d6e
PP
1134 return status;
1135}
1136
1137static inline
50842bdc 1138enum bt_btr_status handle_state(struct bt_btr *btr)
e98a2d6e 1139{
50842bdc 1140 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e 1141
dfef8367
PP
1142 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1143 btr, btr_state_string(btr->state));
1144
e98a2d6e
PP
1145 switch (btr->state) {
1146 case BTR_STATE_NEXT_FIELD:
1147 status = next_field_state(btr);
1148 break;
1149 case BTR_STATE_ALIGN_BASIC:
1150 status = align_type_state(btr, btr->cur_basic_field_type,
1151 BTR_STATE_READ_BASIC_BEGIN);
1152 break;
1153 case BTR_STATE_ALIGN_COMPOUND:
1154 status = align_type_state(btr, stack_top(btr->stack)->base_type,
1155 BTR_STATE_NEXT_FIELD);
1156 break;
1157 case BTR_STATE_READ_BASIC_BEGIN:
1158 status = read_basic_begin_state(btr);
1159 break;
1160 case BTR_STATE_READ_BASIC_CONTINUE:
1161 status = read_basic_continue_state(btr);
1162 break;
1163 case BTR_STATE_DONE:
1164 break;
1165 }
1166
dfef8367 1167 BT_LOGV("Handled state: btr-addr=%p, status=%s",
50842bdc 1168 btr, bt_btr_status_string(status));
e98a2d6e
PP
1169 return status;
1170}
1171
44c440bc 1172BT_HIDDEN
50842bdc 1173struct bt_btr *bt_btr_create(struct bt_btr_cbs cbs, void *data)
e98a2d6e 1174{
50842bdc 1175 struct bt_btr *btr;
e98a2d6e 1176
dfef8367 1177 BT_LOGD_STR("Creating binary type reader (BTR).");
50842bdc 1178 btr = g_new0(struct bt_btr, 1);
e98a2d6e 1179 if (!btr) {
dfef8367 1180 BT_LOGE_STR("Failed to allocate one binary type reader.");
e98a2d6e
PP
1181 goto end;
1182 }
1183
1184 btr->stack = stack_new();
1185 if (!btr->stack) {
dfef8367 1186 BT_LOGE_STR("Cannot create BTR's stack.");
50842bdc 1187 bt_btr_destroy(btr);
e98a2d6e
PP
1188 btr = NULL;
1189 goto end;
1190 }
1191
1192 btr->state = BTR_STATE_NEXT_FIELD;
1193 btr->user.cbs = cbs;
1194 btr->user.data = data;
dfef8367 1195 BT_LOGD("Created BTR: addr=%p", btr);
e98a2d6e
PP
1196
1197end:
1198 return btr;
1199}
1200
44c440bc 1201BT_HIDDEN
50842bdc 1202void bt_btr_destroy(struct bt_btr *btr)
e98a2d6e
PP
1203{
1204 if (btr->stack) {
1205 stack_destroy(btr->stack);
1206 }
1207
dfef8367 1208 BT_LOGD("Destroying BTR: addr=%p", btr);
e98a2d6e
PP
1209 g_free(btr);
1210}
1211
1212static
50842bdc 1213void reset(struct bt_btr *btr)
e98a2d6e 1214{
dfef8367 1215 BT_LOGD("Resetting BTR: addr=%p", btr);
e98a2d6e 1216 stack_clear(btr->stack);
e98a2d6e
PP
1217 stitch_reset(btr);
1218 btr->buf.addr = NULL;
44c440bc 1219 btr->last_bo = -1;
e98a2d6e
PP
1220}
1221
dfef8367 1222static
50842bdc 1223void update_packet_offset(struct bt_btr *btr)
dfef8367
PP
1224{
1225 BT_LOGV("Updating packet offset for next call: "
1226 "btr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1227 btr, btr->buf.packet_offset,
1228 btr->buf.packet_offset + btr->buf.at);
1229 btr->buf.packet_offset += btr->buf.at;
1230}
1231
44c440bc 1232BT_HIDDEN
50842bdc 1233size_t bt_btr_start(struct bt_btr *btr,
44c440bc 1234 struct ctf_field_type *type, const uint8_t *buf,
e98a2d6e 1235 size_t offset, size_t packet_offset, size_t sz,
50842bdc 1236 enum bt_btr_status *status)
e98a2d6e 1237{
f6ccaed9
PP
1238 BT_ASSERT(btr);
1239 BT_ASSERT(BYTES_TO_BITS(sz) >= offset);
e98a2d6e
PP
1240 reset(btr);
1241 btr->buf.addr = buf;
1242 btr->buf.offset = offset;
1243 btr->buf.at = 0;
1244 btr->buf.packet_offset = packet_offset;
1245 btr->buf.buf_sz = sz;
1246 btr->buf.sz = BYTES_TO_BITS(sz) - offset;
50842bdc 1247 *status = BT_BTR_STATUS_OK;
e98a2d6e 1248
dfef8367
PP
1249 BT_LOGV("Starting decoding: btr-addr=%p, ft-addr=%p, "
1250 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1251 "packet-offset=%zu",
1252 btr, type, buf, sz, offset, packet_offset);
1253
e98a2d6e 1254 /* Set root type */
44c440bc 1255 if (type->is_compound) {
e98a2d6e
PP
1256 /* Compound type: push on visit stack */
1257 int stack_ret;
1258
1259 if (btr->user.cbs.types.compound_begin) {
dfef8367 1260 BT_LOGV("Calling user function (compound, begin).");
e98a2d6e
PP
1261 *status = btr->user.cbs.types.compound_begin(
1262 type, btr->user.data);
dfef8367 1263 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1264 bt_btr_status_string(*status));
1265 if (*status != BT_BTR_STATUS_OK) {
dfef8367 1266 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 1267 btr, bt_btr_status_string(*status));
e98a2d6e
PP
1268 goto end;
1269 }
1270 }
1271
1272 stack_ret = stack_push_with_len(btr, type);
1273 if (stack_ret) {
dfef8367 1274 /* stack_push_with_len() logs errors */
50842bdc 1275 *status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
1276 goto end;
1277 }
1278
1279 btr->state = BTR_STATE_ALIGN_COMPOUND;
1280 } else {
1281 /* Basic type: set as current basic type */
1282 btr->cur_basic_field_type = type;
e98a2d6e
PP
1283 btr->state = BTR_STATE_ALIGN_BASIC;
1284 }
1285
1286 /* Run the machine! */
dfef8367
PP
1287 BT_LOGV_STR("Running the state machine.");
1288
e98a2d6e
PP
1289 while (true) {
1290 *status = handle_state(btr);
50842bdc 1291 if (*status != BT_BTR_STATUS_OK ||
fdf0e7a0 1292 btr->state == BTR_STATE_DONE) {
e98a2d6e
PP
1293 break;
1294 }
1295 }
1296
1297 /* Update packet offset for next time */
dfef8367 1298 update_packet_offset(btr);
e98a2d6e
PP
1299
1300end:
1301 return btr->buf.at;
1302}
1303
44c440bc
PP
1304BT_HIDDEN
1305size_t bt_btr_continue(struct bt_btr *btr, const uint8_t *buf, size_t sz,
1306 enum bt_btr_status *status)
e98a2d6e 1307{
f6ccaed9
PP
1308 BT_ASSERT(btr);
1309 BT_ASSERT(buf);
1310 BT_ASSERT(sz > 0);
e98a2d6e
PP
1311 btr->buf.addr = buf;
1312 btr->buf.offset = 0;
1313 btr->buf.at = 0;
1314 btr->buf.buf_sz = sz;
1315 btr->buf.sz = BYTES_TO_BITS(sz);
50842bdc 1316 *status = BT_BTR_STATUS_OK;
e98a2d6e 1317
dfef8367
PP
1318 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1319 btr, buf, sz);
1320
e98a2d6e 1321 /* Continue running the machine */
dfef8367
PP
1322 BT_LOGV_STR("Running the state machine.");
1323
e98a2d6e
PP
1324 while (true) {
1325 *status = handle_state(btr);
50842bdc 1326 if (*status != BT_BTR_STATUS_OK ||
fdf0e7a0 1327 btr->state == BTR_STATE_DONE) {
e98a2d6e
PP
1328 break;
1329 }
1330 }
1331
1332 /* Update packet offset for next time */
dfef8367 1333 update_packet_offset(btr);
e98a2d6e
PP
1334 return btr->buf.at;
1335}
44c440bc
PP
1336
1337BT_HIDDEN
1338void bt_btr_set_unsigned_int_cb(struct bt_btr *btr,
1339 bt_btr_unsigned_int_cb_func cb)
1340{
1341 BT_ASSERT(btr);
1342 BT_ASSERT(cb);
1343 btr->user.cbs.types.unsigned_int = cb;
1344}
This page took 0.102881 seconds and 4 git commands to generate.