LCOV - code coverage report
Current view: top level - src/bitstream - bitstream_read.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 110 110
Test Date: 2026-09-17 22:59:44 Functions: 100.0 % 15 15
Branches: 99.0 % 100 99

             Branch data     Line data    Source code
       1                 :             : /**
       2                 :             :  * @file bitstream_read.c
       3                 :             :  * @brief Bit-level and byte-level read operations.
       4                 :             :  */
       5                 :             : 
       6                 :             : #include "bitstream_internal.h"
       7                 :             : 
       8                 :             : #include <string.h>
       9                 :             : 
      10                 :             : /* ── Internal helpers ────────────────────────────────────────────────── */
      11                 :             : 
      12                 :             : /**
      13                 :             :  * Read a single bit from buf at the given absolute bit position (MSB-first).
      14                 :             :  */
      15                 :  1015742822 : static inline uint8_t read_bit_msb(const uint8_t *buf, uint64_t bit_pos)
      16                 :             : {
      17                 :  1015742822 :     size_t byte_idx = (size_t)(bit_pos / 8);
      18                 :  1015742822 :     uint8_t bit_idx = (uint8_t)(7 - (bit_pos % 8));
      19                 :  1015742822 :     return (uint8_t)((buf[byte_idx] >> bit_idx) & 1);
      20                 :             : }
      21                 :             : 
      22                 :             : /* ── Stateless ROM functions ─────────────────────────────────────────── */
      23                 :             : 
      24                 :   152624334 : tp_result tp_bs_read_bits_at(const uint8_t *buf, uint64_t bit_pos, unsigned int n, uint64_t *out)
      25                 :             : {
      26   [ +  +  +  +  :   152624334 :     if (!buf || !out || n == 0 || n > 64)
             +  +  +  + ]
      27                 :           9 :         return TP_ERR_INVALID_PARAM;
      28                 :             : 
      29                 :   152624325 :     uint64_t val = 0;
      30         [ +  + ]:  1168358734 :     for (unsigned int i = 0; i < n; i++) {
      31                 :  1015734409 :         val = (val << 1) | read_bit_msb(buf, bit_pos + i);
      32                 :             :     }
      33                 :   152624325 :     *out = val;
      34                 :   152624325 :     return TP_OK;
      35                 :             : }
      36                 :             : 
      37                 :          81 : tp_result tp_bs_read_bits_signed_at(const uint8_t *buf, uint64_t bit_pos, unsigned int n,
      38                 :             :                                     int64_t *out)
      39                 :             : {
      40   [ +  +  +  +  :          81 :     if (!buf || !out || n == 0 || n > 64)
             +  +  +  + ]
      41                 :           8 :         return TP_ERR_INVALID_PARAM;
      42                 :             : 
      43                 :             :     uint64_t raw;
      44                 :             :     /* Allocation failure paths are excluded from coverage (LCOV_EXCL). */
      45                 :          73 :     tp_result rc = tp_bs_read_bits_at(buf, bit_pos, n, &raw);
      46                 :          73 :     if (rc != TP_OK) /* LCOV_EXCL_BR_LINE */
      47                 :             :         return rc;   /* LCOV_EXCL_LINE */
      48                 :             : 
      49                 :             :     /* Sign-extend */
      50   [ +  +  +  + ]:          73 :     if (n < 64 && (raw & ((uint64_t)1 << (n - 1)))) {
      51                 :          37 :         raw |= ~(((uint64_t)1 << n) - 1);
      52                 :             :     }
      53                 :          73 :     *out = (int64_t)raw;
      54                 :          73 :     return TP_OK;
      55                 :             : }
      56                 :             : 
      57                 :           9 : tp_result tp_bs_read_varint_u_at(const uint8_t *buf, uint64_t bit_pos, uint64_t *out,
      58                 :             :                                  unsigned int *bits_read)
      59                 :             : {
      60   [ +  +  +  +  :           9 :     if (!buf || !out || !bits_read)
                   +  + ]
      61                 :           4 :         return TP_ERR_INVALID_PARAM;
      62                 :             : 
      63                 :           5 :     uint64_t val = 0;
      64                 :           5 :     unsigned int shift = 0;
      65                 :           5 :     unsigned int total_bits = 0;
      66                 :             : 
      67         [ +  + ]:          17 :     for (int group = 0; group < TP_VARINT_MAX_GROUPS; group++) {
      68                 :             :         uint64_t byte_val;
      69                 :          16 :         tp_result rc = tp_bs_read_bits_at(buf, bit_pos + total_bits, 8, &byte_val);
      70                 :          16 :         if (rc != TP_OK) /* LCOV_EXCL_BR_LINE */
      71                 :             :             return rc;   /* LCOV_EXCL_LINE */
      72                 :          16 :         total_bits += 8;
      73                 :             : 
      74                 :          16 :         val |= (byte_val & 0x7F) << shift;
      75         [ +  + ]:          16 :         if ((byte_val & 0x80) == 0) {
      76                 :           4 :             *out = val;
      77                 :           4 :             *bits_read = total_bits;
      78                 :           4 :             return TP_OK;
      79                 :             :         }
      80                 :          12 :         shift += 7;
      81                 :             :     }
      82                 :             : 
      83                 :           1 :     return TP_ERR_OVERFLOW;
      84                 :             : }
      85                 :             : 
      86                 :             : /* ── Bit-level read ──────────────────────────────────────────────────── */
      87                 :             : 
      88                 :   152027948 : tp_result tp_bs_read_bits(tp_bitstream_reader *r, unsigned int n, uint64_t *out)
      89                 :             : {
      90   [ +  +  +  +  :   152027948 :     if (!r || !out || n == 0 || n > 64)
             +  +  +  + ]
      91                 :           9 :         return TP_ERR_INVALID_PARAM;
      92         [ +  + ]:   152027939 :     if (r->pos + n > r->bit_len)
      93                 :         147 :         return TP_ERR_EOF;
      94                 :             : 
      95                 :             :     /* Both guards above are exactly what tp_bs_read_bits_at
      96                 :             :        validates, so this cannot fail here. */
      97                 :   152027792 :     tp_result rc = tp_bs_read_bits_at(r->buf, r->pos, n, out);
      98                 :   152027792 :     r->pos += n;
      99                 :   152027792 :     return rc;
     100                 :             : }
     101                 :             : 
     102                 :          75 : tp_result tp_bs_read_bits_signed(tp_bitstream_reader *r, unsigned int n, int64_t *out)
     103                 :             : {
     104   [ +  +  +  +  :          75 :     if (!r || !out || n == 0 || n > 64)
             +  +  +  + ]
     105                 :           6 :         return TP_ERR_INVALID_PARAM;
     106         [ +  + ]:          69 :     if (r->pos + n > r->bit_len)
     107                 :           1 :         return TP_ERR_EOF;
     108                 :             : 
     109                 :             :     /* Both guards above are exactly what tp_bs_read_bits_signed_at
     110                 :             :        validates, so this cannot fail here. */
     111                 :          68 :     tp_result rc = tp_bs_read_bits_signed_at(r->buf, r->pos, n, out);
     112                 :          68 :     r->pos += n;
     113                 :          68 :     return rc;
     114                 :             : }
     115                 :             : 
     116                 :        8420 : tp_result tp_bs_read_bit(tp_bitstream_reader *r, uint8_t *out)
     117                 :             : {
     118   [ +  +  +  + ]:        8420 :     if (!r || !out)
     119                 :           4 :         return TP_ERR_INVALID_PARAM;
     120         [ +  + ]:        8416 :     if (r->pos >= r->bit_len)
     121                 :           3 :         return TP_ERR_EOF;
     122                 :             : 
     123                 :        8413 :     *out = read_bit_msb(r->buf, r->pos);
     124                 :        8413 :     r->pos++;
     125                 :        8413 :     return TP_OK;
     126                 :             : }
     127                 :             : 
     128                 :      587536 : tp_result tp_bs_peek_bits(tp_bitstream_reader *r, unsigned int n, uint64_t *out)
     129                 :             : {
     130   [ +  +  +  +  :      587536 :     if (!r || !out || n == 0 || n > 64)
             +  +  +  + ]
     131                 :           6 :         return TP_ERR_INVALID_PARAM;
     132         [ +  + ]:      587530 :     if (r->pos + n > r->bit_len)
     133                 :           6 :         return TP_ERR_EOF;
     134                 :             : 
     135                 :      587524 :     return tp_bs_read_bits_at(r->buf, r->pos, n, out);
     136                 :             : }
     137                 :             : 
     138                 :          21 : tp_result tp_bs_read_bits32(tp_bitstream_reader *r, unsigned int n, uint32_t *out)
     139                 :             : {
     140   [ +  +  +  +  :          21 :     if (!r || !out || n == 0 || n > 32)
             +  +  +  + ]
     141                 :           8 :         return TP_ERR_INVALID_PARAM;
     142                 :             : 
     143                 :             :     uint64_t val;
     144                 :          13 :     tp_result rc = tp_bs_read_bits(r, n, &val);
     145         [ +  - ]:          13 :     if (rc == TP_OK)
     146                 :          13 :         *out = (uint32_t)val;
     147                 :          13 :     return rc;
     148                 :             : }
     149                 :             : 
     150                 :             : /* ── Byte-level read ─────────────────────────────────────────────────── */
     151                 :             : 
     152                 :       20952 : tp_result tp_bs_read_u8(tp_bitstream_reader *r, uint8_t *out)
     153                 :             : {
     154                 :             :     uint64_t val;
     155                 :       20952 :     tp_result rc = tp_bs_read_bits(r, 8, &val);
     156         [ +  + ]:       20952 :     if (rc == TP_OK)
     157                 :       20940 :         *out = (uint8_t)val;
     158                 :       20952 :     return rc;
     159                 :             : }
     160                 :             : 
     161                 :        3447 : tp_result tp_bs_read_u16(tp_bitstream_reader *r, uint16_t *out)
     162                 :             : {
     163                 :             :     uint64_t val;
     164                 :        3447 :     tp_result rc = tp_bs_read_bits(r, 16, &val);
     165         [ +  + ]:        3447 :     if (rc == TP_OK)
     166                 :        3445 :         *out = (uint16_t)val;
     167                 :        3447 :     return rc;
     168                 :             : }
     169                 :             : 
     170                 :       20778 : tp_result tp_bs_read_u32(tp_bitstream_reader *r, uint32_t *out)
     171                 :             : {
     172                 :             :     uint64_t val;
     173                 :       20778 :     tp_result rc = tp_bs_read_bits(r, 32, &val);
     174         [ +  + ]:       20778 :     if (rc == TP_OK)
     175                 :       20757 :         *out = (uint32_t)val;
     176                 :       20778 :     return rc;
     177                 :             : }
     178                 :             : 
     179                 :        9827 : tp_result tp_bs_read_u64(tp_bitstream_reader *r, uint64_t *out)
     180                 :             : {
     181                 :        9827 :     return tp_bs_read_bits(r, 64, out);
     182                 :             : }
     183                 :             : 
     184                 :           5 : tp_result tp_bs_read_bytes(tp_bitstream_reader *r, uint8_t *buf, size_t n)
     185                 :             : {
     186   [ +  +  +  + ]:           5 :     if (!r || !buf)
     187                 :           3 :         return TP_ERR_INVALID_PARAM;
     188                 :             : 
     189         [ +  + ]:           7 :     for (size_t i = 0; i < n; i++) {
     190                 :           6 :         tp_result rc = tp_bs_read_u8(r, &buf[i]);
     191         [ +  + ]:           6 :         if (rc != TP_OK)
     192                 :           1 :             return rc;
     193                 :             :     }
     194                 :           1 :     return TP_OK;
     195                 :             : }
     196                 :             : 
     197                 :       10455 : tp_result tp_bs_reader_direct_ptr(tp_bitstream_reader *r, const uint8_t **ptr, size_t n)
     198                 :             : {
     199   [ +  +  +  + ]:       10455 :     if (!r || !ptr)
     200                 :           3 :         return TP_ERR_INVALID_PARAM;
     201         [ +  + ]:       10452 :     if (!tp_bs_reader_is_byte_aligned(r))
     202                 :           2 :         return TP_ERR_NOT_ALIGNED;
     203         [ +  + ]:       10450 :     if (r->pos + (uint64_t)n * 8 > r->bit_len)
     204                 :         244 :         return TP_ERR_EOF;
     205                 :             : 
     206                 :       10206 :     *ptr = r->buf + (r->pos / 8);
     207                 :       10206 :     r->pos += (uint64_t)n * 8;
     208                 :       10206 :     return TP_OK;
     209                 :             : }
        

Generated by: LCOV version 2.0-1