LCOV - code coverage report
Current view: top level - src/bitstream - bitstream_write.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 99 99
Test Date: 2026-03-09 04:08:32 Functions: 100.0 % 13 13
Branches: 85.7 % 70 60

             Branch data     Line data    Source code
       1                 :             : /**
       2                 :             :  * @file bitstream_write.c
       3                 :             :  * @brief Bit-level and byte-level write operations, buffer append, bulk copy.
       4                 :             :  */
       5                 :             : 
       6                 :             : #include "bitstream_internal.h"
       7                 :             : 
       8                 :             : #include <stdlib.h>
       9                 :             : #include <string.h>
      10                 :             : 
      11                 :             : /* ── Internal helpers ────────────────────────────────────────────────── */
      12                 :             : 
      13                 :      191193 : static tp_result ensure_capacity(tp_bitstream_writer *w, uint64_t n_bits)
      14                 :             : {
      15                 :      191193 :     size_t needed_bytes = (size_t)((w->pos + n_bits + 7) / 8);
      16         [ +  + ]:      191193 :     if (needed_bytes <= w->cap)
      17                 :      191127 :         return TP_OK;
      18                 :             : 
      19                 :             :     size_t new_cap;
      20         [ +  + ]:          66 :     if (w->growth > 0) {
      21                 :          43 :         new_cap = w->cap + w->growth;
      22                 :             :     } else {
      23                 :          23 :         new_cap = w->cap * 2;
      24                 :             :     }
      25         [ +  + ]:          72 :     while (new_cap < needed_bytes)
      26         [ +  - ]:           6 :         new_cap = w->growth > 0 ? new_cap + w->growth : new_cap * 2;
      27                 :             : 
      28                 :             :     /* Allocation failure paths are excluded from coverage (LCOV_EXCL). */
      29                 :          66 :     uint8_t *new_buf = realloc(w->buf, new_cap);
      30         [ -  + ]:          66 :     if (!new_buf)
      31                 :             :         return TP_ERR_ALLOC; /* LCOV_EXCL_LINE */
      32                 :             : 
      33                 :          66 :     memset(new_buf + w->cap, 0, new_cap - w->cap);
      34                 :          66 :     w->buf = new_buf;
      35                 :          66 :     w->cap = new_cap;
      36                 :          66 :     return TP_OK;
      37                 :             : }
      38                 :             : 
      39                 :     1204957 : static inline void write_bit_msb(uint8_t *buf, uint64_t bit_pos, uint8_t val)
      40                 :             : {
      41                 :     1204957 :     size_t byte_idx = (size_t)(bit_pos / 8);
      42                 :     1204957 :     uint8_t bit_idx = (uint8_t)(7 - (bit_pos % 8));
      43         [ +  + ]:     1204957 :     if (val)
      44                 :      456582 :         buf[byte_idx] = (uint8_t)(buf[byte_idx] | (1u << bit_idx));
      45                 :             :     else
      46                 :      748375 :         buf[byte_idx] = (uint8_t)(buf[byte_idx] & ~(1u << bit_idx));
      47                 :     1204957 : }
      48                 :             : 
      49                 :             : /* ── Bit-level write ─────────────────────────────────────────────────── */
      50                 :             : 
      51                 :      191023 : tp_result tp_bs_write_bits(tp_bitstream_writer *w, uint64_t value, unsigned int n)
      52                 :             : {
      53   [ +  +  +  +  :      191023 :     if (!w || n == 0 || n > 64)
                   +  + ]
      54                 :          14 :         return TP_ERR_INVALID_PARAM;
      55                 :             : 
      56                 :      191009 :     tp_result rc = ensure_capacity(w, n);
      57         [ -  + ]:      191009 :     if (rc != TP_OK)
      58                 :             :         return rc; /* LCOV_EXCL_LINE */
      59                 :             : 
      60         [ +  + ]:     1395907 :     for (unsigned int i = 0; i < n; i++) {
      61                 :     1204898 :         uint8_t bit = (uint8_t)((value >> (n - 1 - i)) & 1);
      62                 :     1204898 :         write_bit_msb(w->buf, w->pos, bit);
      63                 :     1204898 :         w->pos++;
      64                 :             :     }
      65                 :      191009 :     return TP_OK;
      66                 :             : }
      67                 :             : 
      68                 :          71 : tp_result tp_bs_write_bits_signed(tp_bitstream_writer *w, int64_t value, unsigned int n)
      69                 :             : {
      70   [ +  +  +  +  :          71 :     if (!w || n == 0 || n > 64)
                   +  + ]
      71                 :           6 :         return TP_ERR_INVALID_PARAM;
      72                 :             : 
      73                 :             :     /* Mask to n bits -- this truncates the sign extension so only the
      74                 :             :      * low n bits are written, exactly as they would appear in a two's
      75                 :             :      * complement representation.  On read-back, tp_bs_read_bits_signed()
      76                 :             :      * will re-extend the MSB. */
      77                 :          65 :     uint64_t raw = (uint64_t)value;
      78         [ +  + ]:          65 :     if (n < 64)
      79                 :          61 :         raw &= ((uint64_t)1 << n) - 1;
      80                 :             : 
      81                 :          65 :     return tp_bs_write_bits(w, raw, n);
      82                 :             : }
      83                 :             : 
      84                 :          29 : tp_result tp_bs_write_bit(tp_bitstream_writer *w, uint8_t value)
      85                 :             : {
      86         [ +  + ]:          29 :     if (!w)
      87                 :           2 :         return TP_ERR_INVALID_PARAM;
      88                 :             : 
      89                 :          27 :     tp_result rc = ensure_capacity(w, 1);
      90         [ -  + ]:          27 :     if (rc != TP_OK)
      91                 :             :         return rc; /* LCOV_EXCL_LINE */
      92                 :             : 
      93                 :          27 :     write_bit_msb(w->buf, w->pos, value & 1);
      94                 :          27 :     w->pos++;
      95                 :          27 :     return TP_OK;
      96                 :             : }
      97                 :             : 
      98                 :         281 : tp_result tp_bs_writer_align_to_byte(tp_bitstream_writer *w)
      99                 :             : {
     100         [ +  + ]:         281 :     if (!w)
     101                 :           2 :         return TP_ERR_INVALID_PARAM;
     102                 :         279 :     uint64_t rem = w->pos % 8;
     103         [ +  + ]:         279 :     if (rem != 0) {
     104                 :         154 :         uint8_t pad = (uint8_t)(8 - rem);
     105                 :         154 :         tp_result rc = ensure_capacity(w, pad);
     106         [ -  + ]:         154 :         if (rc != TP_OK)
     107                 :             :             return rc; /* LCOV_EXCL_LINE */
     108                 :             :         /* Zero bits are already there from calloc/memset */
     109                 :         154 :         w->pos += pad;
     110                 :             :     }
     111                 :         279 :     return TP_OK;
     112                 :             : }
     113                 :             : 
     114                 :             : /* ── Byte-level write ────────────────────────────────────────────────── */
     115                 :             : 
     116                 :        1890 : tp_result tp_bs_write_u8(tp_bitstream_writer *w, uint8_t val)
     117                 :             : {
     118                 :        1890 :     return tp_bs_write_bits(w, val, 8);
     119                 :             : }
     120                 :             : 
     121                 :         216 : tp_result tp_bs_write_u16(tp_bitstream_writer *w, uint16_t val)
     122                 :             : {
     123                 :         216 :     return tp_bs_write_bits(w, val, 16);
     124                 :             : }
     125                 :             : 
     126                 :        1476 : tp_result tp_bs_write_u32(tp_bitstream_writer *w, uint32_t val)
     127                 :             : {
     128                 :        1476 :     return tp_bs_write_bits(w, val, 32);
     129                 :             : }
     130                 :             : 
     131                 :          25 : tp_result tp_bs_write_u64(tp_bitstream_writer *w, uint64_t val)
     132                 :             : {
     133                 :          25 :     return tp_bs_write_bits(w, val, 64);
     134                 :             : }
     135                 :             : 
     136                 :          75 : tp_result tp_bs_write_bytes(tp_bitstream_writer *w, const uint8_t *buf, size_t n)
     137                 :             : {
     138   [ +  +  +  +  :          75 :     if (!w || (!buf && n > 0))
                   +  + ]
     139                 :           4 :         return TP_ERR_INVALID_PARAM;
     140                 :             : 
     141         [ +  + ]:         457 :     for (size_t i = 0; i < n; i++) {
     142                 :         386 :         tp_result rc = tp_bs_write_u8(w, buf[i]);
     143         [ -  + ]:         386 :         if (rc != TP_OK)
     144                 :             :             return rc; /* LCOV_EXCL_LINE */
     145                 :             :     }
     146                 :          71 :     return TP_OK;
     147                 :             : }
     148                 :             : 
     149                 :             : /* ── Buffer append ───────────────────────────────────────────────────── */
     150                 :             : 
     151                 :           4 : tp_result tp_bs_writer_append_buffer(tp_bitstream_writer *w, const uint8_t *buf, uint64_t bit_len)
     152                 :             : {
     153   [ +  +  +  +  :           4 :     if (!w || (!buf && bit_len > 0))
                   +  - ]
     154                 :           2 :         return TP_ERR_INVALID_PARAM;
     155                 :             : 
     156                 :           2 :     tp_result rc = ensure_capacity(w, bit_len);
     157         [ -  + ]:           2 :     if (rc != TP_OK)
     158                 :             :         return rc; /* LCOV_EXCL_LINE */
     159                 :             : 
     160         [ +  + ]:          22 :     for (uint64_t i = 0; i < bit_len; i++) {
     161                 :          20 :         size_t byte_idx = (size_t)(i / 8);
     162                 :          20 :         uint8_t bit_idx = (uint8_t)(7 - (i % 8));
     163                 :          20 :         uint8_t bit = (uint8_t)((buf[byte_idx] >> bit_idx) & 1);
     164                 :          20 :         write_bit_msb(w->buf, w->pos, bit);
     165                 :          20 :         w->pos++;
     166                 :             :     }
     167                 :           2 :     return TP_OK;
     168                 :             : }
     169                 :             : 
     170                 :             : /* ── Bulk copy ───────────────────────────────────────────────────────── */
     171                 :             : 
     172                 :           3 : tp_result tp_bs_copy_bits(tp_bitstream_reader *r, tp_bitstream_writer *w, uint64_t n_bits)
     173                 :             : {
     174   [ +  +  -  + ]:           3 :     if (!r || !w)
     175                 :           1 :         return TP_ERR_INVALID_PARAM;
     176         [ +  + ]:           2 :     if (r->pos + n_bits > r->bit_len)
     177                 :           1 :         return TP_ERR_EOF;
     178                 :             : 
     179                 :           1 :     tp_result rc = ensure_capacity(w, n_bits);
     180         [ -  + ]:           1 :     if (rc != TP_OK)
     181                 :             :         return rc; /* LCOV_EXCL_LINE */
     182                 :             : 
     183         [ +  + ]:          13 :     for (uint64_t i = 0; i < n_bits; i++) {
     184                 :          12 :         size_t byte_idx = (size_t)(r->pos / 8);
     185                 :          12 :         uint8_t bit_idx = (uint8_t)(7 - (r->pos % 8));
     186                 :          12 :         uint8_t bit = (uint8_t)((r->buf[byte_idx] >> bit_idx) & 1);
     187                 :          12 :         write_bit_msb(w->buf, w->pos, bit);
     188                 :          12 :         r->pos++;
     189                 :          12 :         w->pos++;
     190                 :             :     }
     191                 :           1 :     return TP_OK;
     192                 :             : }
        

Generated by: LCOV version 2.0-1