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