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