Branch data Line data Source code
1 : : /**
2 : : * @file bitstream_varint.c
3 : : * @brief VarInt (LEB128 / zigzag) read/write operations.
4 : : */
5 : :
6 : : #include "bitstream_internal.h"
7 : :
8 : : /* ── VarInt read ─────────────────────────────────────────────────────── */
9 : :
10 : 50609911 : tp_result tp_bs_read_varint_u(tp_bitstream_reader *r, uint64_t *out)
11 : : {
12 [ + + + + ]: 50609911 : if (!r || !out)
13 : 3 : return TP_ERR_INVALID_PARAM;
14 : :
15 : 50609908 : uint64_t val = 0;
16 : 50609908 : unsigned int shift = 0;
17 : :
18 [ + + ]: 99847510 : for (int group = 0; group < TP_VARINT_MAX_GROUPS; group++) {
19 [ + + ]: 99847428 : if (r->pos + 8 > r->bit_len)
20 : 50609826 : return TP_ERR_EOF;
21 : :
22 : : /* Allocation failure paths are excluded from coverage (LCOV_EXCL). */
23 : : uint64_t byte_val;
24 : 99847379 : tp_result rc = tp_bs_read_bits(r, 8, &byte_val);
25 [ - + ]: 99847379 : if (rc != TP_OK)
26 : : return rc; /* LCOV_EXCL_LINE */
27 : :
28 : 99847379 : val |= (byte_val & 0x7F) << shift;
29 [ + + ]: 99847379 : if ((byte_val & 0x80) == 0) {
30 : 50609777 : *out = val;
31 : 50609777 : return TP_OK;
32 : : }
33 : 49237602 : shift += 7;
34 : : }
35 : :
36 : 82 : return TP_ERR_OVERFLOW;
37 : : }
38 : :
39 : 1600 : tp_result tp_bs_read_varint_s(tp_bitstream_reader *r, int64_t *out)
40 : : {
41 [ + + + + ]: 1600 : if (!r || !out)
42 : 3 : return TP_ERR_INVALID_PARAM;
43 : :
44 : : uint64_t raw;
45 : 1597 : tp_result rc = tp_bs_read_varint_u(r, &raw);
46 [ + + ]: 1597 : if (rc != TP_OK)
47 : 6 : return rc;
48 : :
49 : : /* Zigzag decode: if low bit set, negate; otherwise keep */
50 [ + + ]: 1591 : if (raw & 1) {
51 : 40 : *out = -((int64_t)(raw >> 1)) - 1;
52 : : } else {
53 : 1551 : *out = (int64_t)(raw >> 1);
54 : : }
55 : 1591 : return TP_OK;
56 : : }
57 : :
58 : : /* ── VarInt write ────────────────────────────────────────────────────── */
59 : :
60 : 48628 : tp_result tp_bs_write_varint_u(tp_bitstream_writer *w, uint64_t value)
61 : : {
62 [ + + ]: 48628 : if (!w)
63 : 2 : return TP_ERR_INVALID_PARAM;
64 : :
65 : : do {
66 : 71235 : uint8_t byte_val = (uint8_t)(value & 0x7F);
67 : 71235 : value >>= 7;
68 [ + + ]: 71235 : if (value != 0)
69 : 22609 : byte_val = (uint8_t)(byte_val | 0x80u);
70 : :
71 : 71235 : tp_result rc = tp_bs_write_bits(w, byte_val, 8);
72 [ - + ]: 71235 : if (rc != TP_OK)
73 : : return rc; /* LCOV_EXCL_LINE */
74 [ + + ]: 71235 : } while (value != 0);
75 : :
76 : 48626 : return TP_OK;
77 : : }
78 : :
79 : 564 : tp_result tp_bs_write_varint_s(tp_bitstream_writer *w, int64_t value)
80 : : {
81 [ + + ]: 564 : if (!w)
82 : 2 : return TP_ERR_INVALID_PARAM;
83 : :
84 : : /* Zigzag encode: cast to unsigned before left shift to avoid UB */
85 : 562 : uint64_t raw = ((uint64_t)value << 1) ^ (uint64_t)(value >> 63);
86 : 562 : return tp_bs_write_varint_u(w, raw);
87 : : }
|