LCOV - code coverage report
Current view: top level - src/bitstream - bitstream_read.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 112 112
Test Date: 2026-03-09 04:08:32 Functions: 100.0 % 15 15
Branches: 86.1 % 108 93

             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                 :  1005083178 : static inline uint8_t read_bit_msb(const uint8_t *buf, uint64_t bit_pos)
      16                 :             : {
      17                 :  1005083178 :     size_t byte_idx = (size_t)(bit_pos / 8);
      18                 :  1005083178 :     uint8_t bit_idx = (uint8_t)(7 - (bit_pos % 8));
      19                 :  1005083178 :     return (uint8_t)((buf[byte_idx] >> bit_idx) & 1);
      20                 :             : }
      21                 :             : 
      22                 :             : /* ── Stateless ROM functions ─────────────────────────────────────────── */
      23                 :             : 
      24                 :   151086009 : tp_result tp_bs_read_bits_at(const uint8_t *buf, uint64_t bit_pos, unsigned int n, uint64_t *out)
      25                 :             : {
      26   [ +  +  +  +  :   151086009 :     if (!buf || !out || n == 0 || n > 64)
             +  +  +  + ]
      27                 :           5 :         return TP_ERR_INVALID_PARAM;
      28                 :             : 
      29                 :   151086004 :     uint64_t val = 0;
      30         [ +  + ]:  1156168799 :     for (unsigned int i = 0; i < n; i++) {
      31                 :  1005082795 :         val = (val << 1) | read_bit_msb(buf, bit_pos + i);
      32                 :             :     }
      33                 :   151086004 :     *out = val;
      34                 :   151086004 :     return TP_OK;
      35                 :             : }
      36                 :             : 
      37                 :          75 : 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   [ +  +  +  +  :          75 :     if (!buf || !out || n == 0 || n > 64)
             +  +  -  + ]
      41                 :           4 :         return TP_ERR_INVALID_PARAM;
      42                 :             : 
      43                 :             :     uint64_t raw;
      44                 :             :     /* Allocation failure paths are excluded from coverage (LCOV_EXCL). */
      45                 :          71 :     tp_result rc = tp_bs_read_bits_at(buf, bit_pos, n, &raw);
      46         [ -  + ]:          71 :     if (rc != TP_OK)
      47                 :             :         return rc; /* LCOV_EXCL_LINE */
      48                 :             : 
      49                 :             :     /* Sign-extend */
      50   [ +  +  +  + ]:          71 :     if (n < 64 && (raw & ((uint64_t)1 << (n - 1)))) {
      51                 :          36 :         raw |= ~(((uint64_t)1 << n) - 1);
      52                 :             :     }
      53                 :          71 :     *out = (int64_t)raw;
      54                 :          71 :     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)
      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                 :   150614020 : tp_result tp_bs_read_bits(tp_bitstream_reader *r, unsigned int n, uint64_t *out)
      89                 :             : {
      90   [ +  +  +  +  :   150614020 :     if (!r || !out || n == 0 || n > 64)
             +  +  +  + ]
      91                 :           5 :         return TP_ERR_INVALID_PARAM;
      92         [ +  + ]:   150614015 :     if (r->pos + n > r->bit_len)
      93                 :          64 :         return TP_ERR_EOF;
      94                 :             : 
      95                 :   150613951 :     tp_result rc = tp_bs_read_bits_at(r->buf, r->pos, n, out);
      96         [ +  - ]:   150613951 :     if (rc == TP_OK)
      97                 :   150613951 :         r->pos += n;
      98                 :   150613951 :     return rc;
      99                 :             : }
     100                 :             : 
     101                 :          71 : tp_result tp_bs_read_bits_signed(tp_bitstream_reader *r, unsigned int n, int64_t *out)
     102                 :             : {
     103   [ +  +  +  -  :          71 :     if (!r || !out || n == 0 || n > 64)
             +  -  -  + ]
     104                 :           2 :         return TP_ERR_INVALID_PARAM;
     105         [ +  + ]:          69 :     if (r->pos + n > r->bit_len)
     106                 :           1 :         return TP_ERR_EOF;
     107                 :             : 
     108                 :          68 :     tp_result rc = tp_bs_read_bits_signed_at(r->buf, r->pos, n, out);
     109         [ +  - ]:          68 :     if (rc == TP_OK)
     110                 :          68 :         r->pos += n;
     111                 :          68 :     return rc;
     112                 :             : }
     113                 :             : 
     114                 :         388 : tp_result tp_bs_read_bit(tp_bitstream_reader *r, uint8_t *out)
     115                 :             : {
     116   [ +  +  -  + ]:         388 :     if (!r || !out)
     117                 :           2 :         return TP_ERR_INVALID_PARAM;
     118         [ +  + ]:         386 :     if (r->pos >= r->bit_len)
     119                 :           3 :         return TP_ERR_EOF;
     120                 :             : 
     121                 :         383 :     *out = read_bit_msb(r->buf, r->pos);
     122                 :         383 :     r->pos++;
     123                 :         383 :     return TP_OK;
     124                 :             : }
     125                 :             : 
     126                 :      471961 : tp_result tp_bs_peek_bits(tp_bitstream_reader *r, unsigned int n, uint64_t *out)
     127                 :             : {
     128   [ +  +  +  -  :      471961 :     if (!r || !out || n == 0 || n > 64)
             +  -  -  + ]
     129                 :           2 :         return TP_ERR_INVALID_PARAM;
     130         [ +  + ]:      471959 :     if (r->pos + n > r->bit_len)
     131                 :           5 :         return TP_ERR_EOF;
     132                 :             : 
     133                 :      471954 :     return tp_bs_read_bits_at(r->buf, r->pos, n, out);
     134                 :             : }
     135                 :             : 
     136                 :          16 : tp_result tp_bs_read_bits32(tp_bitstream_reader *r, unsigned int n, uint32_t *out)
     137                 :             : {
     138   [ +  +  +  -  :          16 :     if (!r || !out || n == 0 || n > 32)
             +  +  +  + ]
     139                 :           4 :         return TP_ERR_INVALID_PARAM;
     140                 :             : 
     141                 :             :     uint64_t val;
     142                 :          12 :     tp_result rc = tp_bs_read_bits(r, n, &val);
     143         [ +  - ]:          12 :     if (rc == TP_OK)
     144                 :          12 :         *out = (uint32_t)val;
     145                 :          12 :     return rc;
     146                 :             : }
     147                 :             : 
     148                 :             : /* ── Byte-level read ─────────────────────────────────────────────────── */
     149                 :             : 
     150                 :        3996 : tp_result tp_bs_read_u8(tp_bitstream_reader *r, uint8_t *out)
     151                 :             : {
     152                 :             :     uint64_t val;
     153                 :        3996 :     tp_result rc = tp_bs_read_bits(r, 8, &val);
     154         [ +  + ]:        3996 :     if (rc == TP_OK)
     155                 :        3984 :         *out = (uint8_t)val;
     156                 :        3996 :     return rc;
     157                 :             : }
     158                 :             : 
     159                 :         634 : tp_result tp_bs_read_u16(tp_bitstream_reader *r, uint16_t *out)
     160                 :             : {
     161                 :             :     uint64_t val;
     162                 :         634 :     tp_result rc = tp_bs_read_bits(r, 16, &val);
     163         [ +  + ]:         634 :     if (rc == TP_OK)
     164                 :         632 :         *out = (uint16_t)val;
     165                 :         634 :     return rc;
     166                 :             : }
     167                 :             : 
     168                 :        3780 : tp_result tp_bs_read_u32(tp_bitstream_reader *r, uint32_t *out)
     169                 :             : {
     170                 :             :     uint64_t val;
     171                 :        3780 :     tp_result rc = tp_bs_read_bits(r, 32, &val);
     172         [ +  + ]:        3780 :     if (rc == TP_OK)
     173                 :        3771 :         *out = (uint32_t)val;
     174                 :        3780 :     return rc;
     175                 :             : }
     176                 :             : 
     177                 :          57 : tp_result tp_bs_read_u64(tp_bitstream_reader *r, uint64_t *out)
     178                 :             : {
     179                 :          57 :     return tp_bs_read_bits(r, 64, out);
     180                 :             : }
     181                 :             : 
     182                 :           5 : tp_result tp_bs_read_bytes(tp_bitstream_reader *r, uint8_t *buf, size_t n)
     183                 :             : {
     184   [ +  +  +  + ]:           5 :     if (!r || !buf)
     185                 :           3 :         return TP_ERR_INVALID_PARAM;
     186                 :             : 
     187         [ +  + ]:           7 :     for (size_t i = 0; i < n; i++) {
     188                 :           6 :         tp_result rc = tp_bs_read_u8(r, &buf[i]);
     189         [ +  + ]:           6 :         if (rc != TP_OK)
     190                 :           1 :             return rc;
     191                 :             :     }
     192                 :           1 :     return TP_OK;
     193                 :             : }
     194                 :             : 
     195                 :         946 : tp_result tp_bs_reader_direct_ptr(tp_bitstream_reader *r, const uint8_t **ptr, size_t n)
     196                 :             : {
     197   [ +  +  -  + ]:         946 :     if (!r || !ptr)
     198                 :           1 :         return TP_ERR_INVALID_PARAM;
     199         [ +  + ]:         945 :     if (!tp_bs_reader_is_byte_aligned(r))
     200                 :           2 :         return TP_ERR_NOT_ALIGNED;
     201         [ +  + ]:         943 :     if (r->pos + (uint64_t)n * 8 > r->bit_len)
     202                 :          18 :         return TP_ERR_EOF;
     203                 :             : 
     204                 :         925 :     *ptr = r->buf + (r->pos / 8);
     205                 :         925 :     r->pos += (uint64_t)n * 8;
     206                 :         925 :     return TP_OK;
     207                 :             : }
        

Generated by: LCOV version 2.0-1