lib: use object pool for event and packet notifications
[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"
e98a2d6e 45
e98a2d6e
PP
46#define DIV8(_x) ((_x) >> 3)
47#define BYTES_TO_BITS(_x) ((_x) * 8)
48#define BITS_TO_BYTES_FLOOR(_x) DIV8(_x)
49#define BITS_TO_BYTES_CEIL(_x) DIV8((_x) + 7)
50#define IN_BYTE_OFFSET(_at) ((_at) & 7)
51
52/* A visit stack entry */
53struct stack_entry {
54 /*
55 * Current type of base field, one of:
56 *
57 * * Structure
58 * * Array
59 * * Sequence
60 * * Variant
61 *
62 * Owned by this.
63 */
50842bdc 64 struct bt_field_type *base_type;
e98a2d6e
PP
65
66 /* Length of base field (always 1 for variant types) */
67 int64_t base_len;
68
69 /* Lndex of next field to read */
70 int64_t index;
71};
72
73/* Visit stack */
74struct stack {
75 /* Entries (struct stack_entry *) (top is last element) */
76 GPtrArray *entries;
77};
78
79/* Reading states */
80enum btr_state {
81 BTR_STATE_NEXT_FIELD,
82 BTR_STATE_ALIGN_BASIC,
83 BTR_STATE_ALIGN_COMPOUND,
84 BTR_STATE_READ_BASIC_BEGIN,
85 BTR_STATE_READ_BASIC_CONTINUE,
86 BTR_STATE_DONE,
87};
88
89/* Binary type reader */
50842bdc 90struct bt_btr {
e98a2d6e
PP
91 /* Bisit stack */
92 struct stack *stack;
93
e98a2d6e 94 /* Current basic field type */
50842bdc 95 struct bt_field_type *cur_basic_field_type;
e98a2d6e
PP
96
97 /* Current state */
98 enum btr_state state;
99
100 /*
101 * Last basic field type's byte order.
102 *
103 * This is used to detect errors since two contiguous basic
104 * types for which the common boundary is not the boundary of
105 * a byte cannot have different byte orders.
106 *
50842bdc 107 * This is set to BT_BYTE_ORDER_UNKNOWN on reset and when
e98a2d6e
PP
108 * the last basic field type was a string type.
109 */
50842bdc 110 enum bt_byte_order last_bo;
e98a2d6e
PP
111
112 /* Current byte order (copied to last_bo after a successful read) */
50842bdc 113 enum bt_byte_order cur_bo;
e98a2d6e
PP
114
115 /* Stitch buffer infos */
116 struct {
117 /* Stitch buffer */
118 uint8_t buf[16];
119
120 /* Offset, within stitch buffer, of first bit */
121 size_t offset;
122
123 /* Length (bits) of data in stitch buffer from offset */
124 size_t at;
125 } stitch;
126
127 /* User buffer infos */
128 struct {
129 /* Address */
130 const uint8_t *addr;
131
132 /* Offset of data from address (bits) */
133 size_t offset;
134
135 /* Current position from offset (bits) */
136 size_t at;
137
138 /* Offset of offset within whole packet (bits) */
139 size_t packet_offset;
140
141 /* Data size in buffer (bits) */
142 size_t sz;
143
144 /* Buffer size (bytes) */
145 size_t buf_sz;
146 } buf;
147
148 /* User stuff */
149 struct {
150 /* Callback functions */
50842bdc 151 struct bt_btr_cbs cbs;
e98a2d6e
PP
152
153 /* Private data */
154 void *data;
155 } user;
156};
157
dfef8367
PP
158static inline
159const char *btr_state_string(enum btr_state state)
160{
161 switch (state) {
162 case BTR_STATE_NEXT_FIELD:
163 return "BTR_STATE_NEXT_FIELD";
164 case BTR_STATE_ALIGN_BASIC:
165 return "BTR_STATE_ALIGN_BASIC";
166 case BTR_STATE_ALIGN_COMPOUND:
167 return "BTR_STATE_ALIGN_COMPOUND";
168 case BTR_STATE_READ_BASIC_BEGIN:
169 return "BTR_STATE_READ_BASIC_BEGIN";
170 case BTR_STATE_READ_BASIC_CONTINUE:
171 return "BTR_STATE_READ_BASIC_CONTINUE";
172 case BTR_STATE_DONE:
173 return "BTR_STATE_DONE";
174 default:
175 return "(unknown)";
176 }
177}
178
e98a2d6e
PP
179static
180void stack_entry_free_func(gpointer data)
181{
182 struct stack_entry *entry = data;
183
e98a2d6e
PP
184 g_free(entry);
185}
186
187static
188struct stack *stack_new(void)
189{
190 struct stack *stack = NULL;
191
192 stack = g_new0(struct stack, 1);
193 if (!stack) {
dfef8367 194 BT_LOGE_STR("Failed to allocate one stack.");
e98a2d6e
PP
195 goto error;
196 }
197
198 stack->entries = g_ptr_array_new_with_free_func(stack_entry_free_func);
199 if (!stack->entries) {
dfef8367 200 BT_LOGE_STR("Failed to allocate a GPtrArray.");
e98a2d6e
PP
201 goto error;
202 }
203
dfef8367 204 BT_LOGD("Created stack: addr=%p", stack);
e98a2d6e
PP
205 return stack;
206
207error:
208 g_free(stack);
209
210 return NULL;
211}
212
213static
214void stack_destroy(struct stack *stack)
215{
216 if (!stack) {
217 return;
218 }
219
dfef8367 220 BT_LOGD("Destroying stack: addr=%p", stack);
e98a2d6e
PP
221 g_ptr_array_free(stack->entries, TRUE);
222 g_free(stack);
223}
224
225static inline
50842bdc
PP
226int64_t get_compound_field_type_length(struct bt_btr *btr,
227 struct bt_field_type *field_type)
e98a2d6e
PP
228{
229 int64_t length;
230
50842bdc
PP
231 switch (bt_field_type_get_type_id(field_type)) {
232 case BT_FIELD_TYPE_ID_STRUCT:
233 length = (int64_t) bt_field_type_structure_get_field_count(
e98a2d6e
PP
234 field_type);
235 break;
50842bdc 236 case BT_FIELD_TYPE_ID_VARIANT:
e98a2d6e
PP
237 /* Variant field types always "contain" a single type */
238 length = 1;
239 break;
50842bdc
PP
240 case BT_FIELD_TYPE_ID_ARRAY:
241 length = bt_field_type_array_get_length(field_type);
e98a2d6e 242 break;
50842bdc 243 case BT_FIELD_TYPE_ID_SEQUENCE:
e98a2d6e
PP
244 length = btr->user.cbs.query.get_sequence_length(field_type,
245 btr->user.data);
246 break;
247 default:
dfef8367
PP
248 BT_LOGW("Cannot get field type's field count: btr-addr=%p, "
249 "ft-addr=%p, ft-id=%s",
250 btr, field_type,
3dca2276 251 bt_common_field_type_id_string(
50842bdc
PP
252 bt_field_type_get_type_id(field_type)));
253 length = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
254 }
255
256 return length;
257}
258
259static
50842bdc 260int stack_push(struct stack *stack, struct bt_field_type *base_type,
e98a2d6e
PP
261 size_t base_len)
262{
263 int ret = 0;
264 struct stack_entry *entry;
265
f6ccaed9
PP
266 BT_ASSERT(stack);
267 BT_ASSERT(base_type);
dfef8367
PP
268 BT_LOGV("Pushing field type on stack: stack-addr=%p, "
269 "ft-addr=%p, ft-id=%s, base-length=%zu, "
270 "stack-size-before=%u, stack-size-after=%u",
3dca2276 271 stack, base_type, bt_common_field_type_id_string(
50842bdc 272 bt_field_type_get_type_id(base_type)),
dfef8367 273 base_len, stack->entries->len, stack->entries->len + 1);
e98a2d6e
PP
274 entry = g_new0(struct stack_entry, 1);
275 if (!entry) {
dfef8367
PP
276 BT_LOGE("Failed to allocate one stack entry: stack-addr=%p",
277 stack);
50842bdc 278 ret = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
279 goto end;
280 }
281
282 entry->base_type = base_type;
e98a2d6e
PP
283 entry->base_len = base_len;
284 g_ptr_array_add(stack->entries, entry);
285
286end:
287 return ret;
288}
289
290static
50842bdc
PP
291int stack_push_with_len(struct bt_btr *btr,
292 struct bt_field_type *base_type)
e98a2d6e
PP
293{
294 int ret = 0;
295 int64_t base_len = get_compound_field_type_length(btr, base_type);
296
297 if (base_len < 0) {
dfef8367
PP
298 BT_LOGW("Cannot get compound field type's field count: "
299 "btr-addr=%p, ft-addr=%p, ft-id=%s",
3dca2276 300 btr, base_type, bt_common_field_type_id_string(
50842bdc
PP
301 bt_field_type_get_type_id(base_type)));
302 ret = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
303 goto end;
304 }
305
306 ret = stack_push(btr->stack, base_type, (size_t) base_len);
307
308end:
309 return ret;
310}
311
312static inline
313unsigned int stack_size(struct stack *stack)
314{
f6ccaed9 315 BT_ASSERT(stack);
e98a2d6e
PP
316 return stack->entries->len;
317}
318
319static
320void stack_pop(struct stack *stack)
321{
f6ccaed9
PP
322 BT_ASSERT(stack);
323 BT_ASSERT(stack_size(stack));
dfef8367
PP
324 BT_LOGV("Popping from stack: "
325 "stack-addr=%p, stack-size-before=%u, stack-size-after=%u",
326 stack, stack->entries->len, stack->entries->len - 1);
e98a2d6e
PP
327 g_ptr_array_remove_index(stack->entries, stack->entries->len - 1);
328}
329
330static inline
331bool stack_empty(struct stack *stack)
332{
333 return stack_size(stack) == 0;
334}
335
336static
337void stack_clear(struct stack *stack)
338{
f6ccaed9 339 BT_ASSERT(stack);
e98a2d6e
PP
340
341 if (!stack_empty(stack)) {
342 g_ptr_array_remove_range(stack->entries, 0, stack_size(stack));
343 }
344
f6ccaed9 345 BT_ASSERT(stack_empty(stack));
e98a2d6e
PP
346}
347
348static inline
349struct stack_entry *stack_top(struct stack *stack)
350{
f6ccaed9
PP
351 BT_ASSERT(stack);
352 BT_ASSERT(stack_size(stack));
e98a2d6e
PP
353
354 return g_ptr_array_index(stack->entries, stack->entries->len - 1);
355}
356
357static inline
50842bdc 358size_t available_bits(struct bt_btr *btr)
e98a2d6e
PP
359{
360 return btr->buf.sz - btr->buf.at;
361}
362
363static inline
50842bdc 364void consume_bits(struct bt_btr *btr, size_t incr)
e98a2d6e 365{
dfef8367
PP
366 BT_LOGV("Advancing cursor: btr-addr=%p, cur-before=%zu, cur-after=%zu",
367 btr, btr->buf.at, btr->buf.at + incr);
e98a2d6e
PP
368 btr->buf.at += incr;
369}
370
371static inline
50842bdc 372bool has_enough_bits(struct bt_btr *btr, size_t sz)
e98a2d6e
PP
373{
374 return available_bits(btr) >= sz;
375}
376
377static inline
50842bdc 378bool at_least_one_bit_left(struct bt_btr *btr)
e98a2d6e
PP
379{
380 return has_enough_bits(btr, 1);
381}
382
383static inline
50842bdc 384size_t packet_at(struct bt_btr *btr)
e98a2d6e
PP
385{
386 return btr->buf.packet_offset + btr->buf.at;
387}
388
389static inline
50842bdc 390size_t buf_at_from_addr(struct bt_btr *btr)
e98a2d6e
PP
391{
392 /*
393 * Considering this:
394 *
395 * ====== offset ===== (17)
396 *
397 * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
398 * ^
399 * addr (0) ==== at ==== (12)
400 *
401 * We want this:
402 *
403 * =============================== (29)
404 */
405 return btr->buf.offset + btr->buf.at;
406}
407
408static inline
50842bdc
PP
409int get_basic_field_type_size(struct bt_btr *btr,
410 struct bt_field_type *field_type)
e98a2d6e
PP
411{
412 int size;
413
50842bdc
PP
414 switch (bt_field_type_get_type_id(field_type)) {
415 case BT_FIELD_TYPE_ID_INTEGER:
416 size = bt_field_type_integer_get_size(field_type);
e98a2d6e 417 break;
50842bdc 418 case BT_FIELD_TYPE_ID_FLOAT:
e98a2d6e
PP
419 {
420 int exp_dig, mant_dig;
421
422 exp_dig =
50842bdc 423 bt_field_type_floating_point_get_exponent_digits(
e98a2d6e
PP
424 field_type);
425 mant_dig =
50842bdc 426 bt_field_type_floating_point_get_mantissa_digits(
e98a2d6e 427 field_type);
f6ccaed9
PP
428 BT_ASSERT(exp_dig >= 0);
429 BT_ASSERT(mant_dig >= 0);
e98a2d6e
PP
430 size = exp_dig + mant_dig;
431 break;
432 }
50842bdc 433 case BT_FIELD_TYPE_ID_ENUM:
e98a2d6e 434 {
50842bdc 435 struct bt_field_type *int_type;
e98a2d6e 436
5ae32b51
PP
437 int_type =
438 bt_field_type_enumeration_borrow_container_field_type(
439 field_type);
f6ccaed9 440 BT_ASSERT(int_type);
e98a2d6e 441 size = get_basic_field_type_size(btr, int_type);
e98a2d6e
PP
442 break;
443 }
444 default:
50842bdc 445 size = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
446 break;
447 }
448
e98a2d6e
PP
449 return size;
450}
451
452static
50842bdc 453void stitch_reset(struct bt_btr *btr)
e98a2d6e
PP
454{
455 btr->stitch.offset = 0;
456 btr->stitch.at = 0;
457}
458
459static inline
50842bdc 460size_t stitch_at_from_addr(struct bt_btr *btr)
e98a2d6e
PP
461{
462 return btr->stitch.offset + btr->stitch.at;
463}
464
465static
50842bdc 466void stitch_append_from_buf(struct bt_btr *btr, size_t sz)
e98a2d6e
PP
467{
468 size_t stitch_byte_at;
469 size_t buf_byte_at;
5ae32b51 470 size_t nb_bytes;
e98a2d6e
PP
471
472 if (sz == 0) {
473 return;
474 }
475
476 stitch_byte_at =
477 BITS_TO_BYTES_FLOOR(stitch_at_from_addr(btr));
478 buf_byte_at = BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr));
479 nb_bytes = BITS_TO_BYTES_CEIL(sz);
f6ccaed9
PP
480 BT_ASSERT(nb_bytes > 0);
481 BT_ASSERT(btr->buf.addr);
e98a2d6e
PP
482 memcpy(&btr->stitch.buf[stitch_byte_at], &btr->buf.addr[buf_byte_at],
483 nb_bytes);
484 btr->stitch.at += sz;
485 consume_bits(btr, sz);
486}
487
488static
50842bdc 489void stitch_append_from_remaining_buf(struct bt_btr *btr)
e98a2d6e
PP
490{
491 stitch_append_from_buf(btr, available_bits(btr));
492}
493
494static
50842bdc 495void stitch_set_from_remaining_buf(struct bt_btr *btr)
e98a2d6e
PP
496{
497 stitch_reset(btr);
498 btr->stitch.offset = IN_BYTE_OFFSET(buf_at_from_addr(btr));
499 stitch_append_from_remaining_buf(btr);
500}
501
502static inline
50842bdc
PP
503enum bt_btr_status read_unsigned_bitfield(const uint8_t *buf, size_t at,
504 int64_t field_size, enum bt_byte_order bo, uint64_t *v)
e98a2d6e 505{
50842bdc 506 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
507
508 switch (bo) {
50842bdc
PP
509 case BT_BYTE_ORDER_BIG_ENDIAN:
510 case BT_BYTE_ORDER_NETWORK:
e98a2d6e
PP
511 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
512 break;
50842bdc 513 case BT_BYTE_ORDER_LITTLE_ENDIAN:
e98a2d6e
PP
514 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
515 break;
516 default:
dfef8367
PP
517 BT_LOGF("Cannot read unsigned bit array: unknown byte order: bo=%d", bo);
518 abort();
e98a2d6e
PP
519 }
520
dfef8367
PP
521 BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64 ", "
522 "bo=%s, val=%" PRIu64, at, field_size,
3dca2276 523 bt_common_byte_order_string(bo), *v);
e98a2d6e
PP
524 return status;
525}
526
527static inline
50842bdc
PP
528enum bt_btr_status read_signed_bitfield(const uint8_t *buf, size_t at,
529 int64_t field_size, enum bt_byte_order bo, int64_t *v)
e98a2d6e 530{
50842bdc 531 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
532
533 switch (bo) {
50842bdc
PP
534 case BT_BYTE_ORDER_BIG_ENDIAN:
535 case BT_BYTE_ORDER_NETWORK:
e98a2d6e
PP
536 bt_bitfield_read_be(buf, uint8_t, at, field_size, v);
537 break;
50842bdc 538 case BT_BYTE_ORDER_LITTLE_ENDIAN:
e98a2d6e
PP
539 bt_bitfield_read_le(buf, uint8_t, at, field_size, v);
540 break;
541 default:
dfef8367
PP
542 BT_LOGF("Cannot read signed bit array: unknown byte order: bo=%d", bo);
543 abort();
e98a2d6e
PP
544 }
545
dfef8367
PP
546 BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64 ", "
547 "bo=%s, val=%" PRId64, at, field_size,
3dca2276 548 bt_common_byte_order_string(bo), *v);
e98a2d6e
PP
549 return status;
550}
551
50842bdc 552typedef enum bt_btr_status (* read_basic_and_call_cb_t)(struct bt_btr *,
dfef8367 553 const uint8_t *, size_t);
e98a2d6e
PP
554
555static inline
50842bdc
PP
556enum bt_btr_status validate_contiguous_bo(struct bt_btr *btr,
557 enum bt_byte_order next_bo)
e98a2d6e 558{
50842bdc 559 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
560
561 /* Always valid when at a byte boundary */
562 if (packet_at(btr) % 8 == 0) {
563 goto end;
564 }
565
566 /* Always valid if last byte order is unknown */
50842bdc 567 if (btr->last_bo == BT_BYTE_ORDER_UNKNOWN) {
e98a2d6e
PP
568 goto end;
569 }
570
571 /* Always valid if next byte order is unknown */
50842bdc 572 if (next_bo == BT_BYTE_ORDER_UNKNOWN) {
e98a2d6e
PP
573 goto end;
574 }
575
576 /* Make sure last byte order is compatible with the next byte order */
577 switch (btr->last_bo) {
50842bdc
PP
578 case BT_BYTE_ORDER_BIG_ENDIAN:
579 case BT_BYTE_ORDER_NETWORK:
580 if (next_bo != BT_BYTE_ORDER_BIG_ENDIAN &&
581 next_bo != BT_BYTE_ORDER_NETWORK) {
582 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
583 }
584 break;
50842bdc
PP
585 case BT_BYTE_ORDER_LITTLE_ENDIAN:
586 if (next_bo != BT_BYTE_ORDER_LITTLE_ENDIAN) {
587 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
588 }
589 break;
590 default:
50842bdc 591 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
592 }
593
594end:
fdf0e7a0 595 if (status < 0) {
dfef8367
PP
596 BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
597 "btr-addr=%p, last-bo=%s, next-bo=%s",
3dca2276
PP
598 btr, bt_common_byte_order_string(btr->last_bo),
599 bt_common_byte_order_string(next_bo));
dfef8367
PP
600 }
601
e98a2d6e
PP
602 return status;
603}
604
605static
50842bdc 606enum bt_btr_status read_basic_float_and_call_cb(struct bt_btr *btr,
dfef8367 607 const uint8_t *buf, size_t at)
e98a2d6e
PP
608{
609 int ret;
610 double dblval;
611 int64_t field_size;
50842bdc
PP
612 enum bt_byte_order bo;
613 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
614
615 field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
50842bdc 616 bo = bt_field_type_get_byte_order(btr->cur_basic_field_type);
e98a2d6e
PP
617 btr->cur_bo = bo;
618
619 switch (field_size) {
620 case 32:
621 {
622 uint64_t v;
623 union {
624 uint32_t u;
625 float f;
626 } f32;
627
50842bdc 628 ret = bt_field_type_floating_point_get_mantissa_digits(
e98a2d6e 629 btr->cur_basic_field_type);
f6ccaed9 630 BT_ASSERT(ret == 24);
50842bdc 631 ret = bt_field_type_floating_point_get_exponent_digits(
e98a2d6e 632 btr->cur_basic_field_type);
f6ccaed9 633 BT_ASSERT(ret == 8);
e98a2d6e 634 status = read_unsigned_bitfield(buf, at, field_size, bo, &v);
50842bdc 635 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
636 BT_LOGW("Cannot read unsigned 32-bit bit array for floating point number field: "
637 "btr-addr=%p, status=%s",
50842bdc 638 btr, bt_btr_status_string(status));
e98a2d6e
PP
639 goto end;
640 }
641
642 f32.u = (uint32_t) v;
643 dblval = (double) f32.f;
644 break;
645 }
646 case 64:
647 {
648 union {
649 uint64_t u;
650 double d;
651 } f64;
652
50842bdc 653 ret = bt_field_type_floating_point_get_mantissa_digits(
e98a2d6e 654 btr->cur_basic_field_type);
f6ccaed9 655 BT_ASSERT(ret == 53);
50842bdc 656 ret = bt_field_type_floating_point_get_exponent_digits(
e98a2d6e 657 btr->cur_basic_field_type);
f6ccaed9 658 BT_ASSERT(ret == 11);
e98a2d6e
PP
659 status = read_unsigned_bitfield(buf, at, field_size, bo,
660 &f64.u);
50842bdc 661 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
662 BT_LOGW("Cannot read unsigned 64-bit bit array for floating point number field: "
663 "btr-addr=%p, status=%s",
50842bdc 664 btr, bt_btr_status_string(status));
e98a2d6e
PP
665 goto end;
666 }
667
668 dblval = f64.d;
669 break;
670 }
671 default:
672 /* Only 32-bit and 64-bit fields are supported currently */
dfef8367
PP
673 BT_LOGW("Only 32-bit and 64-bit floating point number fields are supported: "
674 "btr-addr=%p", btr);
50842bdc 675 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
676 goto end;
677 }
678
dfef8367
PP
679 BT_LOGV("Read floating point number value: btr=%p, cur=%zu, val=%f",
680 btr, at, dblval);
681
e98a2d6e 682 if (btr->user.cbs.types.floating_point) {
dfef8367 683 BT_LOGV("Calling user function (floating point number).");
e98a2d6e
PP
684 status = btr->user.cbs.types.floating_point(dblval,
685 btr->cur_basic_field_type, btr->user.data);
dfef8367 686 BT_LOGV("User function returned: status=%s",
50842bdc
PP
687 bt_btr_status_string(status));
688 if (status != BT_BTR_STATUS_OK) {
dfef8367 689 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 690 btr, bt_btr_status_string(status));
dfef8367 691 }
e98a2d6e
PP
692 }
693
694end:
695 return status;
696}
697
698static inline
50842bdc 699enum bt_btr_status read_basic_int_and_call(struct bt_btr *btr,
dfef8367 700 const uint8_t *buf, size_t at,
50842bdc
PP
701 struct bt_field_type *int_type,
702 struct bt_field_type *orig_type)
e98a2d6e 703{
50842bdc 704 bt_bool signd;
e98a2d6e 705 int64_t field_size;
50842bdc
PP
706 enum bt_byte_order bo;
707 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e 708
50842bdc 709 signd = bt_field_type_integer_is_signed(int_type);
e98a2d6e
PP
710 field_size = get_basic_field_type_size(btr, int_type);
711 if (field_size < 1) {
dfef8367
PP
712 BT_LOGW("Cannot get integer field type's size: "
713 "btr=%p, at=%zu, ft-addr=%p",
714 btr, at, int_type);
50842bdc 715 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
716 goto end;
717 }
718
50842bdc 719 bo = bt_field_type_get_byte_order(int_type);
e98a2d6e
PP
720
721 /*
722 * Update current byte order now because we could be reading
723 * the integer value of an enumeration type, and thus we know
724 * here the actual supporting integer type's byte order.
725 */
726 btr->cur_bo = bo;
727
728 if (signd) {
729 int64_t v;
730
731 status = read_signed_bitfield(buf, at, field_size, bo, &v);
50842bdc 732 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
733 BT_LOGW("Cannot read signed bit array for signed integer field: "
734 "btr-addr=%p, status=%s",
50842bdc 735 btr, bt_btr_status_string(status));
e98a2d6e
PP
736 goto end;
737 }
738
739 if (btr->user.cbs.types.signed_int) {
dfef8367 740 BT_LOGV("Calling user function (signed integer).");
e98a2d6e
PP
741 status = btr->user.cbs.types.signed_int(v,
742 btr->cur_basic_field_type, btr->user.data);
dfef8367 743 BT_LOGV("User function returned: status=%s",
50842bdc
PP
744 bt_btr_status_string(status));
745 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
746 BT_LOGW("User function failed: "
747 "btr-addr=%p, status=%s",
50842bdc 748 btr, bt_btr_status_string(status));
dfef8367 749 }
e98a2d6e
PP
750 }
751 } else {
752 uint64_t v;
753
754 status = read_unsigned_bitfield(buf, at, field_size, bo, &v);
50842bdc 755 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
756 BT_LOGW("Cannot read unsigned bit array for unsigned integer field: "
757 "btr-addr=%p, status=%s",
50842bdc 758 btr, bt_btr_status_string(status));
e98a2d6e
PP
759 goto end;
760 }
761
762 if (btr->user.cbs.types.unsigned_int) {
dfef8367 763 BT_LOGV("Calling user function (unsigned integer).");
e98a2d6e
PP
764 status = btr->user.cbs.types.unsigned_int(v,
765 btr->cur_basic_field_type, btr->user.data);
dfef8367 766 BT_LOGV("User function returned: status=%s",
50842bdc
PP
767 bt_btr_status_string(status));
768 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
769 BT_LOGW("User function failed: "
770 "btr-addr=%p, status=%s",
50842bdc 771 btr, bt_btr_status_string(status));
dfef8367 772 }
e98a2d6e
PP
773 }
774 }
775
776end:
777 return status;
778}
779
780static
50842bdc 781enum bt_btr_status read_basic_int_and_call_cb(struct bt_btr *btr,
dfef8367 782 const uint8_t *buf, size_t at)
e98a2d6e
PP
783{
784 return read_basic_int_and_call(btr, buf, at, btr->cur_basic_field_type,
785 btr->cur_basic_field_type);
786}
787
788static
50842bdc 789enum bt_btr_status read_basic_enum_and_call_cb(struct bt_btr *btr,
dfef8367 790 const uint8_t *buf, size_t at)
e98a2d6e 791{
50842bdc
PP
792 struct bt_field_type *int_field_type;
793 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e 794
5ae32b51 795 int_field_type = bt_field_type_enumeration_borrow_container_field_type(
e98a2d6e 796 btr->cur_basic_field_type);
f6ccaed9 797 BT_ASSERT(int_field_type);
e98a2d6e
PP
798 status = read_basic_int_and_call(btr, buf, at,
799 int_field_type, btr->cur_basic_field_type);
e98a2d6e
PP
800 return status;
801}
802
803static inline
50842bdc 804enum bt_btr_status read_basic_type_and_call_continue(struct bt_btr *btr,
dfef8367 805 read_basic_and_call_cb_t read_basic_and_call_cb)
e98a2d6e
PP
806{
807 size_t available;
808 int64_t field_size;
809 int64_t needed_bits;
50842bdc 810 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
811
812 if (!at_least_one_bit_left(btr)) {
dfef8367 813 BT_LOGV("Reached end of data: btr-addr=%p", btr);
50842bdc 814 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
815 goto end;
816 }
817
818 field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
819 if (field_size < 1) {
dfef8367
PP
820 BT_LOGW("Cannot get basic field type's size: "
821 "btr-addr=%p, ft-addr=%p",
822 btr, btr->cur_basic_field_type);
50842bdc 823 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
824 goto end;
825 }
826
827 available = available_bits(btr);
828 needed_bits = field_size - btr->stitch.at;
dfef8367
PP
829 BT_LOGV("Continuing basic field decoding: "
830 "btr-addr=%p, field-size=%" PRId64 ", needed-size=%" PRId64 ", "
831 "available-size=%zu",
832 btr, field_size, needed_bits, available);
e98a2d6e
PP
833 if (needed_bits <= available) {
834 /* We have all the bits; append to stitch, then decode */
835 stitch_append_from_buf(btr, needed_bits);
836 status = read_basic_and_call_cb(btr, btr->stitch.buf,
837 btr->stitch.offset);
50842bdc 838 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
839 BT_LOGW("Cannot read basic field: "
840 "btr-addr=%p, ft-addr=%p, status=%s",
841 btr, btr->cur_basic_field_type,
50842bdc 842 bt_btr_status_string(status));
e98a2d6e
PP
843 goto end;
844 }
845
846 if (stack_empty(btr->stack)) {
847 /* Root is a basic type */
848 btr->state = BTR_STATE_DONE;
849 } else {
850 /* Go to next field */
851 stack_top(btr->stack)->index++;
852 btr->state = BTR_STATE_NEXT_FIELD;
853 btr->last_bo = btr->cur_bo;
854 }
855 goto end;
856 }
857
858 /* We are here; it means we don't have enough data to decode this */
dfef8367 859 BT_LOGV_STR("Not enough data to read the next basic field: appending to stitch buffer.");
e98a2d6e 860 stitch_append_from_remaining_buf(btr);
50842bdc 861 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
862
863end:
864 return status;
865}
866
867static inline
50842bdc 868enum bt_btr_status read_basic_type_and_call_begin(struct bt_btr *btr,
dfef8367 869 read_basic_and_call_cb_t read_basic_and_call_cb)
e98a2d6e
PP
870{
871 size_t available;
872 int64_t field_size;
50842bdc
PP
873 enum bt_byte_order bo;
874 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
875
876 if (!at_least_one_bit_left(btr)) {
dfef8367 877 BT_LOGV("Reached end of data: btr-addr=%p", btr);
50842bdc 878 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
879 goto end;
880 }
881
882 field_size = get_basic_field_type_size(btr, btr->cur_basic_field_type);
e98a2d6e 883 if (field_size < 1) {
dfef8367
PP
884 BT_LOGW("Cannot get basic field type's size: "
885 "btr-addr=%p, ft-addr=%p",
886 btr, btr->cur_basic_field_type);
50842bdc 887 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
888 goto end;
889 }
890
50842bdc 891 bo = bt_field_type_get_byte_order(btr->cur_basic_field_type);
e98a2d6e 892 status = validate_contiguous_bo(btr, bo);
50842bdc 893 if (status != BT_BTR_STATUS_OK) {
dfef8367 894 /* validate_contiguous_bo() logs errors */
e98a2d6e
PP
895 goto end;
896 }
897
898 available = available_bits(btr);
899
900 if (field_size <= available) {
901 /* We have all the bits; decode and set now */
f6ccaed9 902 BT_ASSERT(btr->buf.addr);
e98a2d6e
PP
903 status = read_basic_and_call_cb(btr, btr->buf.addr,
904 buf_at_from_addr(btr));
50842bdc 905 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
906 BT_LOGW("Cannot read basic field: "
907 "btr-addr=%p, ft-addr=%p, status=%s",
908 btr, btr->cur_basic_field_type,
50842bdc 909 bt_btr_status_string(status));
e98a2d6e
PP
910 goto end;
911 }
912
913 consume_bits(btr, field_size);
914
915 if (stack_empty(btr->stack)) {
916 /* Root is a basic type */
917 btr->state = BTR_STATE_DONE;
918 } else {
919 /* Go to next field */
920 stack_top(btr->stack)->index++;
921 btr->state = BTR_STATE_NEXT_FIELD;
922 btr->last_bo = btr->cur_bo;
923 }
924
925 goto end;
926 }
927
928 /* We are here; it means we don't have enough data to decode this */
dfef8367 929 BT_LOGV_STR("Not enough data to read the next basic field: setting stitch buffer.");
e98a2d6e
PP
930 stitch_set_from_remaining_buf(btr);
931 btr->state = BTR_STATE_READ_BASIC_CONTINUE;
50842bdc 932 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
933
934end:
935 return status;
936}
937
938static inline
50842bdc
PP
939enum bt_btr_status read_basic_int_type_and_call_begin(
940 struct bt_btr *btr)
e98a2d6e
PP
941{
942 return read_basic_type_and_call_begin(btr, read_basic_int_and_call_cb);
943}
944
945static inline
50842bdc
PP
946enum bt_btr_status read_basic_int_type_and_call_continue(
947 struct bt_btr *btr)
e98a2d6e
PP
948{
949 return read_basic_type_and_call_continue(btr,
950 read_basic_int_and_call_cb);
951}
952
953static inline
50842bdc
PP
954enum bt_btr_status read_basic_float_type_and_call_begin(
955 struct bt_btr *btr)
e98a2d6e
PP
956{
957 return read_basic_type_and_call_begin(btr,
958 read_basic_float_and_call_cb);
959}
960
961static inline
50842bdc
PP
962enum bt_btr_status read_basic_float_type_and_call_continue(
963 struct bt_btr *btr)
e98a2d6e
PP
964{
965 return read_basic_type_and_call_continue(btr,
966 read_basic_float_and_call_cb);
967}
968
969static inline
50842bdc
PP
970enum bt_btr_status read_basic_enum_type_and_call_begin(
971 struct bt_btr *btr)
e98a2d6e
PP
972{
973 return read_basic_type_and_call_begin(btr,
974 read_basic_enum_and_call_cb);
975}
976
977static inline
50842bdc
PP
978enum bt_btr_status read_basic_enum_type_and_call_continue(
979 struct bt_btr *btr)
e98a2d6e
PP
980{
981 return read_basic_type_and_call_continue(btr,
982 read_basic_enum_and_call_cb);
983}
984
985static inline
50842bdc
PP
986enum bt_btr_status read_basic_string_type_and_call(
987 struct bt_btr *btr, bool begin)
e98a2d6e
PP
988{
989 size_t buf_at_bytes;
990 const uint8_t *result;
991 size_t available_bytes;
992 const uint8_t *first_chr;
50842bdc 993 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
994
995 if (!at_least_one_bit_left(btr)) {
dfef8367 996 BT_LOGV("Reached end of data: btr-addr=%p", btr);
50842bdc 997 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
998 goto end;
999 }
1000
f6ccaed9 1001 BT_ASSERT(buf_at_from_addr(btr) % 8 == 0);
e98a2d6e
PP
1002 available_bytes = BITS_TO_BYTES_FLOOR(available_bits(btr));
1003 buf_at_bytes = BITS_TO_BYTES_FLOOR(buf_at_from_addr(btr));
f6ccaed9 1004 BT_ASSERT(btr->buf.addr);
e98a2d6e
PP
1005 first_chr = &btr->buf.addr[buf_at_bytes];
1006 result = memchr(first_chr, '\0', available_bytes);
1007
1008 if (begin && btr->user.cbs.types.string_begin) {
dfef8367 1009 BT_LOGV("Calling user function (string, beginning).");
e98a2d6e
PP
1010 status = btr->user.cbs.types.string_begin(
1011 btr->cur_basic_field_type, btr->user.data);
dfef8367 1012 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1013 bt_btr_status_string(status));
1014 if (status != BT_BTR_STATUS_OK) {
dfef8367 1015 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 1016 btr, bt_btr_status_string(status));
e98a2d6e
PP
1017 goto end;
1018 }
1019 }
1020
1021 if (!result) {
1022 /* No null character yet */
1023 if (btr->user.cbs.types.string) {
dfef8367 1024 BT_LOGV("Calling user function (substring).");
e98a2d6e
PP
1025 status = btr->user.cbs.types.string(
1026 (const char *) first_chr,
1027 available_bytes, btr->cur_basic_field_type,
1028 btr->user.data);
dfef8367 1029 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1030 bt_btr_status_string(status));
1031 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
1032 BT_LOGW("User function failed: "
1033 "btr-addr=%p, status=%s",
50842bdc 1034 btr, bt_btr_status_string(status));
e98a2d6e
PP
1035 goto end;
1036 }
1037 }
1038
1039 consume_bits(btr, BYTES_TO_BITS(available_bytes));
1040 btr->state = BTR_STATE_READ_BASIC_CONTINUE;
50842bdc 1041 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
1042 } else {
1043 /* Found the null character */
1044 size_t result_len = (size_t) (result - first_chr);
1045
1046 if (btr->user.cbs.types.string && result_len) {
dfef8367 1047 BT_LOGV("Calling user function (substring).");
e98a2d6e
PP
1048 status = btr->user.cbs.types.string(
1049 (const char *) first_chr,
1050 result_len, btr->cur_basic_field_type,
1051 btr->user.data);
dfef8367 1052 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1053 bt_btr_status_string(status));
1054 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
1055 BT_LOGW("User function failed: "
1056 "btr-addr=%p, status=%s",
50842bdc 1057 btr, bt_btr_status_string(status));
e98a2d6e
PP
1058 goto end;
1059 }
1060 }
1061
1062 if (btr->user.cbs.types.string_end) {
dfef8367 1063 BT_LOGV("Calling user function (string, end).");
e98a2d6e
PP
1064 status = btr->user.cbs.types.string_end(
1065 btr->cur_basic_field_type, btr->user.data);
dfef8367 1066 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1067 bt_btr_status_string(status));
1068 if (status != BT_BTR_STATUS_OK) {
dfef8367
PP
1069 BT_LOGW("User function failed: "
1070 "btr-addr=%p, status=%s",
50842bdc 1071 btr, bt_btr_status_string(status));
e98a2d6e
PP
1072 goto end;
1073 }
1074 }
1075
1076 consume_bits(btr, BYTES_TO_BITS(result_len + 1));
1077
1078 if (stack_empty(btr->stack)) {
1079 /* Root is a basic type */
1080 btr->state = BTR_STATE_DONE;
1081 } else {
1082 /* Go to next field */
1083 stack_top(btr->stack)->index++;
1084 btr->state = BTR_STATE_NEXT_FIELD;
1085 btr->last_bo = btr->cur_bo;
1086 }
1087 }
1088
1089end:
1090 return status;
1091}
1092
1093static inline
50842bdc 1094enum bt_btr_status read_basic_begin_state(struct bt_btr *btr)
e98a2d6e 1095{
50842bdc 1096 enum bt_btr_status status;
e98a2d6e 1097
f6ccaed9 1098 BT_ASSERT(btr->cur_basic_field_type);
e98a2d6e 1099
50842bdc
PP
1100 switch (bt_field_type_get_type_id(btr->cur_basic_field_type)) {
1101 case BT_FIELD_TYPE_ID_INTEGER:
e98a2d6e
PP
1102 status = read_basic_int_type_and_call_begin(btr);
1103 break;
50842bdc 1104 case BT_FIELD_TYPE_ID_FLOAT:
e98a2d6e
PP
1105 status = read_basic_float_type_and_call_begin(btr);
1106 break;
50842bdc 1107 case BT_FIELD_TYPE_ID_ENUM:
e98a2d6e
PP
1108 status = read_basic_enum_type_and_call_begin(btr);
1109 break;
50842bdc 1110 case BT_FIELD_TYPE_ID_STRING:
e98a2d6e
PP
1111 status = read_basic_string_type_and_call(btr, true);
1112 break;
1113 default:
dfef8367
PP
1114 BT_LOGF("Unknown basic field type ID: "
1115 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1116 btr, btr->cur_basic_field_type,
3dca2276 1117 bt_common_field_type_id_string(
50842bdc 1118 bt_field_type_get_type_id(
dfef8367 1119 btr->cur_basic_field_type)));
0fbb9a9f 1120 abort();
e98a2d6e
PP
1121 }
1122
1123 return status;
1124}
1125
1126static inline
50842bdc 1127enum bt_btr_status read_basic_continue_state(struct bt_btr *btr)
e98a2d6e 1128{
50842bdc 1129 enum bt_btr_status status;
e98a2d6e 1130
f6ccaed9 1131 BT_ASSERT(btr->cur_basic_field_type);
e98a2d6e 1132
50842bdc
PP
1133 switch (bt_field_type_get_type_id(btr->cur_basic_field_type)) {
1134 case BT_FIELD_TYPE_ID_INTEGER:
e98a2d6e
PP
1135 status = read_basic_int_type_and_call_continue(btr);
1136 break;
50842bdc 1137 case BT_FIELD_TYPE_ID_FLOAT:
e98a2d6e
PP
1138 status = read_basic_float_type_and_call_continue(btr);
1139 break;
50842bdc 1140 case BT_FIELD_TYPE_ID_ENUM:
e98a2d6e
PP
1141 status = read_basic_enum_type_and_call_continue(btr);
1142 break;
50842bdc 1143 case BT_FIELD_TYPE_ID_STRING:
e98a2d6e
PP
1144 status = read_basic_string_type_and_call(btr, false);
1145 break;
1146 default:
dfef8367
PP
1147 BT_LOGF("Unknown basic field type ID: "
1148 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1149 btr, btr->cur_basic_field_type,
3dca2276 1150 bt_common_field_type_id_string(
50842bdc 1151 bt_field_type_get_type_id(
dfef8367 1152 btr->cur_basic_field_type)));
0fbb9a9f 1153 abort();
e98a2d6e
PP
1154 }
1155
1156 return status;
1157}
1158
1159static inline
50842bdc 1160size_t bits_to_skip_to_align_to(struct bt_btr *btr, size_t align)
e98a2d6e
PP
1161{
1162 size_t aligned_packet_at;
1163
1164 aligned_packet_at = ALIGN(packet_at(btr), align);
e98a2d6e
PP
1165 return aligned_packet_at - packet_at(btr);
1166}
1167
1168static inline
50842bdc
PP
1169enum bt_btr_status align_type_state(struct bt_btr *btr,
1170 struct bt_field_type *field_type, enum btr_state next_state)
e98a2d6e
PP
1171{
1172 int field_alignment;
1173 size_t skip_bits;
50842bdc 1174 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
1175
1176 /* Get field's alignment */
50842bdc 1177 field_alignment = bt_field_type_get_alignment(field_type);
e98a2d6e 1178 if (field_alignment < 0) {
dfef8367
PP
1179 BT_LOGW("Cannot get field type's alignment: "
1180 "btr-addr=%p, ft-addr=%p, ft-id=%s",
1181 btr, field_type,
3dca2276 1182 bt_common_field_type_id_string(
50842bdc
PP
1183 bt_field_type_get_type_id(field_type)));
1184 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
1185 goto end;
1186 }
1187
1188 /*
1189 * 0 means "undefined" for variants; what we really want is 1
1190 * (always aligned)
1191 */
1192 if (field_alignment == 0) {
1193 field_alignment = 1;
1194 }
1195
1196 /* Compute how many bits we need to skip */
1197 skip_bits = bits_to_skip_to_align_to(btr, field_alignment);
1198
1199 /* Nothing to skip? aligned */
1200 if (skip_bits == 0) {
1201 btr->state = next_state;
1202 goto end;
1203 }
1204
1205 /* Make sure there's at least one bit left */
1206 if (!at_least_one_bit_left(btr)) {
50842bdc 1207 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
1208 goto end;
1209 }
1210
1211 /* Consume as many bits as possible in what's left */
1212 consume_bits(btr, MIN(available_bits(btr), skip_bits));
1213
1214 /* Are we done now? */
1215 skip_bits = bits_to_skip_to_align_to(btr, field_alignment);
e98a2d6e
PP
1216 if (skip_bits == 0) {
1217 /* Yes: go to next state */
1218 btr->state = next_state;
1219 goto end;
1220 } else {
1221 /* No: need more data */
dfef8367 1222 BT_LOGV("Reached end of data when aligning: btr-addr=%p", btr);
50842bdc 1223 status = BT_BTR_STATUS_EOF;
e98a2d6e
PP
1224 }
1225
1226end:
1227 return status;
1228}
1229
1230static inline
50842bdc 1231bool is_compound_type(struct bt_field_type *field_type)
e98a2d6e 1232{
50842bdc 1233 enum bt_field_type_id id = bt_field_type_get_type_id(field_type);
e98a2d6e 1234
50842bdc
PP
1235 return id == BT_FIELD_TYPE_ID_STRUCT || id == BT_FIELD_TYPE_ID_ARRAY ||
1236 id == BT_FIELD_TYPE_ID_SEQUENCE || id == BT_FIELD_TYPE_ID_VARIANT;
e98a2d6e
PP
1237}
1238
1239static inline
50842bdc 1240enum bt_btr_status next_field_state(struct bt_btr *btr)
e98a2d6e
PP
1241{
1242 int ret;
1243 struct stack_entry *top;
50842bdc
PP
1244 struct bt_field_type *next_field_type = NULL;
1245 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e
PP
1246
1247 if (stack_empty(btr->stack)) {
1248 goto end;
1249 }
1250
1251 top = stack_top(btr->stack);
1252
1253 /* Are we done with this base type? */
1254 while (top->index == top->base_len) {
1255 if (btr->user.cbs.types.compound_end) {
dfef8367 1256 BT_LOGV("Calling user function (compound, end).");
e98a2d6e
PP
1257 status = btr->user.cbs.types.compound_end(
1258 top->base_type, btr->user.data);
dfef8367 1259 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1260 bt_btr_status_string(status));
1261 if (status != BT_BTR_STATUS_OK) {
dfef8367 1262 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 1263 btr, bt_btr_status_string(status));
e98a2d6e
PP
1264 goto end;
1265 }
1266 }
1267
1268 stack_pop(btr->stack);
1269
1270 /* Are we done with the root type? */
1271 if (stack_empty(btr->stack)) {
1272 btr->state = BTR_STATE_DONE;
1273 goto end;
1274 }
1275
1276 top = stack_top(btr->stack);
1277 top->index++;
1278 }
1279
1280 /* Get next field's type */
50842bdc
PP
1281 switch (bt_field_type_get_type_id(top->base_type)) {
1282 case BT_FIELD_TYPE_ID_STRUCT:
5ae32b51 1283 ret = bt_field_type_structure_borrow_field_by_index(
e98a2d6e
PP
1284 top->base_type, NULL, &next_field_type,
1285 top->index);
1286 if (ret) {
1287 next_field_type = NULL;
1288 }
1289 break;
50842bdc 1290 case BT_FIELD_TYPE_ID_ARRAY:
e98a2d6e 1291 next_field_type =
5ae32b51 1292 bt_field_type_array_borrow_element_field_type(
e98a2d6e
PP
1293 top->base_type);
1294 break;
50842bdc 1295 case BT_FIELD_TYPE_ID_SEQUENCE:
e98a2d6e 1296 next_field_type =
5ae32b51 1297 bt_field_type_sequence_borrow_element_field_type(
e98a2d6e
PP
1298 top->base_type);
1299 break;
50842bdc 1300 case BT_FIELD_TYPE_ID_VARIANT:
e98a2d6e
PP
1301 /* Variant types are dynamic: query the user, he should know! */
1302 next_field_type =
5ae32b51 1303 btr->user.cbs.query.borrow_variant_field_type(
e98a2d6e
PP
1304 top->base_type, btr->user.data);
1305 break;
1306 default:
1307 break;
1308 }
1309
1310 if (!next_field_type) {
dfef8367
PP
1311 BT_LOGW("Cannot get the field type of the next field: "
1312 "btr-addr=%p, base-ft-addr=%p, base-ft-id=%s, "
1313 "index=%" PRId64,
1314 btr, top->base_type,
3dca2276 1315 bt_common_field_type_id_string(
50842bdc 1316 bt_field_type_get_type_id(top->base_type)),
dfef8367 1317 top->index);
50842bdc 1318 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
1319 goto end;
1320 }
1321
1322 if (is_compound_type(next_field_type)) {
1323 if (btr->user.cbs.types.compound_begin) {
dfef8367 1324 BT_LOGV("Calling user function (compound, begin).");
e98a2d6e
PP
1325 status = btr->user.cbs.types.compound_begin(
1326 next_field_type, btr->user.data);
dfef8367 1327 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1328 bt_btr_status_string(status));
1329 if (status != BT_BTR_STATUS_OK) {
dfef8367 1330 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 1331 btr, bt_btr_status_string(status));
e98a2d6e
PP
1332 goto end;
1333 }
1334 }
1335
1336 ret = stack_push_with_len(btr, next_field_type);
1337 if (ret) {
dfef8367 1338 /* stack_push_with_len() logs errors */
50842bdc 1339 status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
1340 goto end;
1341 }
1342
1343 /* Next state: align a compound type */
1344 btr->state = BTR_STATE_ALIGN_COMPOUND;
1345 } else {
1346 /* Replace current basic field type */
dfef8367
PP
1347 BT_LOGV("Replacing current basic field type: "
1348 "btr-addr=%p, cur-basic-ft-addr=%p, "
1349 "next-basic-ft-addr=%p",
1350 btr, btr->cur_basic_field_type, next_field_type);
5ae32b51 1351 btr->cur_basic_field_type = next_field_type;
e98a2d6e
PP
1352
1353 /* Next state: align a basic type */
1354 btr->state = BTR_STATE_ALIGN_BASIC;
1355 }
1356
1357end:
e98a2d6e
PP
1358 return status;
1359}
1360
1361static inline
50842bdc 1362enum bt_btr_status handle_state(struct bt_btr *btr)
e98a2d6e 1363{
50842bdc 1364 enum bt_btr_status status = BT_BTR_STATUS_OK;
e98a2d6e 1365
dfef8367
PP
1366 BT_LOGV("Handling state: btr-addr=%p, state=%s",
1367 btr, btr_state_string(btr->state));
1368
e98a2d6e
PP
1369 switch (btr->state) {
1370 case BTR_STATE_NEXT_FIELD:
1371 status = next_field_state(btr);
1372 break;
1373 case BTR_STATE_ALIGN_BASIC:
1374 status = align_type_state(btr, btr->cur_basic_field_type,
1375 BTR_STATE_READ_BASIC_BEGIN);
1376 break;
1377 case BTR_STATE_ALIGN_COMPOUND:
1378 status = align_type_state(btr, stack_top(btr->stack)->base_type,
1379 BTR_STATE_NEXT_FIELD);
1380 break;
1381 case BTR_STATE_READ_BASIC_BEGIN:
1382 status = read_basic_begin_state(btr);
1383 break;
1384 case BTR_STATE_READ_BASIC_CONTINUE:
1385 status = read_basic_continue_state(btr);
1386 break;
1387 case BTR_STATE_DONE:
1388 break;
1389 }
1390
dfef8367 1391 BT_LOGV("Handled state: btr-addr=%p, status=%s",
50842bdc 1392 btr, bt_btr_status_string(status));
e98a2d6e
PP
1393 return status;
1394}
1395
50842bdc 1396struct bt_btr *bt_btr_create(struct bt_btr_cbs cbs, void *data)
e98a2d6e 1397{
50842bdc 1398 struct bt_btr *btr;
e98a2d6e 1399
dfef8367 1400 BT_LOGD_STR("Creating binary type reader (BTR).");
50842bdc 1401 btr = g_new0(struct bt_btr, 1);
e98a2d6e 1402 if (!btr) {
dfef8367 1403 BT_LOGE_STR("Failed to allocate one binary type reader.");
e98a2d6e
PP
1404 goto end;
1405 }
1406
1407 btr->stack = stack_new();
1408 if (!btr->stack) {
dfef8367 1409 BT_LOGE_STR("Cannot create BTR's stack.");
50842bdc 1410 bt_btr_destroy(btr);
e98a2d6e
PP
1411 btr = NULL;
1412 goto end;
1413 }
1414
1415 btr->state = BTR_STATE_NEXT_FIELD;
1416 btr->user.cbs = cbs;
1417 btr->user.data = data;
dfef8367 1418 BT_LOGD("Created BTR: addr=%p", btr);
e98a2d6e
PP
1419
1420end:
1421 return btr;
1422}
1423
50842bdc 1424void bt_btr_destroy(struct bt_btr *btr)
e98a2d6e
PP
1425{
1426 if (btr->stack) {
1427 stack_destroy(btr->stack);
1428 }
1429
dfef8367 1430 BT_LOGD("Destroying BTR: addr=%p", btr);
e98a2d6e
PP
1431 g_free(btr);
1432}
1433
1434static
50842bdc 1435void reset(struct bt_btr *btr)
e98a2d6e 1436{
dfef8367 1437 BT_LOGD("Resetting BTR: addr=%p", btr);
e98a2d6e 1438 stack_clear(btr->stack);
e98a2d6e
PP
1439 stitch_reset(btr);
1440 btr->buf.addr = NULL;
50842bdc 1441 btr->last_bo = BT_BYTE_ORDER_UNKNOWN;
e98a2d6e
PP
1442}
1443
dfef8367 1444static
50842bdc 1445void update_packet_offset(struct bt_btr *btr)
dfef8367
PP
1446{
1447 BT_LOGV("Updating packet offset for next call: "
1448 "btr-addr=%p, cur-packet-offset=%zu, next-packet-offset=%zu",
1449 btr, btr->buf.packet_offset,
1450 btr->buf.packet_offset + btr->buf.at);
1451 btr->buf.packet_offset += btr->buf.at;
1452}
1453
50842bdc
PP
1454size_t bt_btr_start(struct bt_btr *btr,
1455 struct bt_field_type *type, const uint8_t *buf,
e98a2d6e 1456 size_t offset, size_t packet_offset, size_t sz,
50842bdc 1457 enum bt_btr_status *status)
e98a2d6e 1458{
f6ccaed9
PP
1459 BT_ASSERT(btr);
1460 BT_ASSERT(BYTES_TO_BITS(sz) >= offset);
e98a2d6e
PP
1461 reset(btr);
1462 btr->buf.addr = buf;
1463 btr->buf.offset = offset;
1464 btr->buf.at = 0;
1465 btr->buf.packet_offset = packet_offset;
1466 btr->buf.buf_sz = sz;
1467 btr->buf.sz = BYTES_TO_BITS(sz) - offset;
50842bdc 1468 *status = BT_BTR_STATUS_OK;
e98a2d6e 1469
dfef8367
PP
1470 BT_LOGV("Starting decoding: btr-addr=%p, ft-addr=%p, "
1471 "buf-addr=%p, buf-size=%zu, offset=%zu, "
1472 "packet-offset=%zu",
1473 btr, type, buf, sz, offset, packet_offset);
1474
e98a2d6e
PP
1475 /* Set root type */
1476 if (is_compound_type(type)) {
1477 /* Compound type: push on visit stack */
1478 int stack_ret;
1479
1480 if (btr->user.cbs.types.compound_begin) {
dfef8367 1481 BT_LOGV("Calling user function (compound, begin).");
e98a2d6e
PP
1482 *status = btr->user.cbs.types.compound_begin(
1483 type, btr->user.data);
dfef8367 1484 BT_LOGV("User function returned: status=%s",
50842bdc
PP
1485 bt_btr_status_string(*status));
1486 if (*status != BT_BTR_STATUS_OK) {
dfef8367 1487 BT_LOGW("User function failed: btr-addr=%p, status=%s",
50842bdc 1488 btr, bt_btr_status_string(*status));
e98a2d6e
PP
1489 goto end;
1490 }
1491 }
1492
1493 stack_ret = stack_push_with_len(btr, type);
1494 if (stack_ret) {
dfef8367 1495 /* stack_push_with_len() logs errors */
50842bdc 1496 *status = BT_BTR_STATUS_ERROR;
e98a2d6e
PP
1497 goto end;
1498 }
1499
1500 btr->state = BTR_STATE_ALIGN_COMPOUND;
1501 } else {
1502 /* Basic type: set as current basic type */
1503 btr->cur_basic_field_type = type;
e98a2d6e
PP
1504 btr->state = BTR_STATE_ALIGN_BASIC;
1505 }
1506
1507 /* Run the machine! */
dfef8367
PP
1508 BT_LOGV_STR("Running the state machine.");
1509
e98a2d6e
PP
1510 while (true) {
1511 *status = handle_state(btr);
50842bdc 1512 if (*status != BT_BTR_STATUS_OK ||
fdf0e7a0 1513 btr->state == BTR_STATE_DONE) {
e98a2d6e
PP
1514 break;
1515 }
1516 }
1517
1518 /* Update packet offset for next time */
dfef8367 1519 update_packet_offset(btr);
e98a2d6e
PP
1520
1521end:
1522 return btr->buf.at;
1523}
1524
50842bdc 1525size_t bt_btr_continue(struct bt_btr *btr,
e98a2d6e 1526 const uint8_t *buf, size_t sz,
50842bdc 1527 enum bt_btr_status *status)
e98a2d6e 1528{
f6ccaed9
PP
1529 BT_ASSERT(btr);
1530 BT_ASSERT(buf);
1531 BT_ASSERT(sz > 0);
e98a2d6e
PP
1532 btr->buf.addr = buf;
1533 btr->buf.offset = 0;
1534 btr->buf.at = 0;
1535 btr->buf.buf_sz = sz;
1536 btr->buf.sz = BYTES_TO_BITS(sz);
50842bdc 1537 *status = BT_BTR_STATUS_OK;
e98a2d6e 1538
dfef8367
PP
1539 BT_LOGV("Continuing decoding: btr-addr=%p, buf-addr=%p, buf-size=%zu",
1540 btr, buf, sz);
1541
e98a2d6e 1542 /* Continue running the machine */
dfef8367
PP
1543 BT_LOGV_STR("Running the state machine.");
1544
e98a2d6e
PP
1545 while (true) {
1546 *status = handle_state(btr);
50842bdc 1547 if (*status != BT_BTR_STATUS_OK ||
fdf0e7a0 1548 btr->state == BTR_STATE_DONE) {
e98a2d6e
PP
1549 break;
1550 }
1551 }
1552
1553 /* Update packet offset for next time */
dfef8367 1554 update_packet_offset(btr);
e98a2d6e
PP
1555 return btr->buf.at;
1556}
This page took 0.109459 seconds and 4 git commands to generate.