LCOV - code coverage report
Current view: top level - src/core - value.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 110 110
Test Date: 2026-03-09 04:08:32 Functions: 100.0 % 2 2
Branches: 88.7 % 62 55

             Branch data     Line data    Source code
       1                 :             : /**
       2                 :             :  * @file value.c
       3                 :             :  * @brief Value encoding and decoding helpers for typed trie terminals.
       4                 :             :  *
       5                 :             :  * Copyright (c) 2026 M. A. Chatterjee <deftio at deftio dot com>
       6                 :             :  * BSD-2-Clause — see LICENSE.txt
       7                 :             :  */
       8                 :             : 
       9                 :             : #include "core_internal.h"
      10                 :             : 
      11                 :       10762 : tp_result tp_value_encode(tp_bitstream_writer *w, const tp_value *val)
      12                 :             : {
      13   [ +  +  +  + ]:       10762 :     if (!w || !val)
      14                 :           2 :         return TP_ERR_INVALID_PARAM;
      15                 :             : 
      16                 :             :     /* Allocation failure paths are excluded from coverage (LCOV_EXCL). */
      17                 :             :     /* Write 4-bit type tag */
      18                 :       10760 :     tp_result rc = tp_bs_write_bits(w, (uint64_t)val->type, 4);
      19         [ -  + ]:       10760 :     if (rc != TP_OK)
      20                 :             :         return rc; /* LCOV_EXCL_LINE */
      21                 :             : 
      22   [ +  +  +  +  :       10760 :     switch (val->type) {
          +  +  +  +  +  
                      - ]
      23                 :          10 :     case TP_NULL:
      24                 :          10 :         break;
      25                 :          24 :     case TP_BOOL:
      26                 :          24 :         rc = tp_bs_write_bit(w, val->data.bool_val ? 1 : 0);
      27                 :          24 :         break;
      28                 :         548 :     case TP_INT:
      29                 :         548 :         rc = tp_bs_write_varint_s(w, val->data.int_val);
      30                 :         548 :         break;
      31                 :       10079 :     case TP_UINT:
      32                 :       10079 :         rc = tp_bs_write_varint_u(w, val->data.uint_val);
      33                 :       10079 :         break;
      34                 :           9 :     case TP_FLOAT32: {
      35                 :             :         uint32_t bits;
      36                 :           9 :         memcpy(&bits, &val->data.float32_val, sizeof(bits));
      37                 :           9 :         rc = tp_bs_write_u32(w, bits);
      38                 :           9 :         break;
      39                 :             :     }
      40                 :          20 :     case TP_FLOAT64: {
      41                 :             :         uint64_t bits;
      42                 :          20 :         memcpy(&bits, &val->data.float64_val, sizeof(bits));
      43                 :          20 :         rc = tp_bs_write_u64(w, bits);
      44                 :          20 :         break;
      45                 :             :     }
      46                 :          59 :     case TP_STRING: {
      47                 :          59 :         rc = tp_bs_write_varint_u(w, val->data.string_val.str_len);
      48         [ -  + ]:          59 :         if (rc != TP_OK)
      49                 :             :             return rc; /* LCOV_EXCL_LINE */
      50                 :             :         /* Align to byte boundary before writing raw string data */
      51                 :          59 :         rc = tp_bs_writer_align_to_byte(w);
      52         [ -  + ]:          59 :         if (rc != TP_OK)
      53                 :             :             return rc; /* LCOV_EXCL_LINE */
      54                 :          59 :         rc = tp_bs_write_bytes(w, (const uint8_t *)val->data.string_val.str,
      55                 :          59 :                                val->data.string_val.str_len);
      56                 :          59 :         break;
      57                 :             :     }
      58                 :           9 :     case TP_BLOB: {
      59                 :           9 :         rc = tp_bs_write_varint_u(w, val->data.blob_val.len);
      60         [ -  + ]:           9 :         if (rc != TP_OK)
      61                 :             :             return rc; /* LCOV_EXCL_LINE */
      62                 :             :         /* Align to byte boundary before writing raw blob data */
      63                 :           9 :         rc = tp_bs_writer_align_to_byte(w);
      64         [ -  + ]:           9 :         if (rc != TP_OK)
      65                 :             :             return rc; /* LCOV_EXCL_LINE */
      66                 :           9 :         rc = tp_bs_write_bytes(w, val->data.blob_val.data, val->data.blob_val.len);
      67                 :           9 :         break;
      68                 :             :     }
      69                 :           2 :     case TP_ARRAY:
      70                 :             :     case TP_DICT:
      71                 :           2 :         return TP_ERR_INVALID_PARAM; /* deferred */
      72                 :             :     }
      73                 :       10758 :     return rc;
      74                 :             : }
      75                 :             : 
      76                 :    50009546 : tp_result tp_value_decode(tp_bitstream_reader *r, tp_value *val, const uint8_t *base_buf)
      77                 :             : {
      78   [ +  +  +  + ]:    50009546 :     if (!r || !val)
      79                 :           2 :         return TP_ERR_INVALID_PARAM;
      80                 :             : 
      81                 :    50009544 :     memset(val, 0, sizeof(*val));
      82                 :             : 
      83                 :             :     uint64_t tag;
      84                 :    50009544 :     tp_result rc = tp_bs_read_bits(r, 4, &tag);
      85         [ +  + ]:    50009544 :     if (rc != TP_OK)
      86                 :           3 :         return rc;
      87                 :    50009541 :     val->type = (tp_value_type)tag;
      88                 :             : 
      89   [ +  +  +  +  :    50009541 :     switch (val->type) {
          +  +  +  +  +  
                      + ]
      90                 :         169 :     case TP_NULL:
      91                 :         169 :         break;
      92                 :         380 :     case TP_BOOL: {
      93                 :             :         uint8_t bit;
      94                 :         380 :         rc = tp_bs_read_bit(r, &bit);
      95         [ +  + ]:         380 :         if (rc == TP_OK)
      96                 :         379 :             val->data.bool_val = (bit != 0);
      97                 :         380 :         break;
      98                 :             :     }
      99                 :        1586 :     case TP_INT:
     100                 :        1586 :         rc = tp_bs_read_varint_s(r, &val->data.int_val);
     101                 :        1586 :         break;
     102                 :    50006210 :     case TP_UINT:
     103                 :    50006210 :         rc = tp_bs_read_varint_u(r, &val->data.uint_val);
     104                 :    50006210 :         break;
     105                 :          23 :     case TP_FLOAT32: {
     106                 :             :         uint32_t bits;
     107                 :          23 :         rc = tp_bs_read_u32(r, &bits);
     108         [ +  + ]:          23 :         if (rc == TP_OK)
     109                 :          21 :             memcpy(&val->data.float32_val, &bits, sizeof(float));
     110                 :          23 :         break;
     111                 :             :     }
     112                 :          53 :     case TP_FLOAT64: {
     113                 :             :         uint64_t bits;
     114                 :          53 :         rc = tp_bs_read_u64(r, &bits);
     115         [ +  + ]:          53 :         if (rc == TP_OK)
     116                 :          50 :             memcpy(&val->data.float64_val, &bits, sizeof(double));
     117                 :          53 :         break;
     118                 :             :     }
     119                 :         930 :     case TP_STRING: {
     120                 :             :         uint64_t slen;
     121                 :         930 :         rc = tp_bs_read_varint_u(r, &slen);
     122         [ +  + ]:         930 :         if (rc != TP_OK)
     123                 :           4 :             return rc;
     124                 :             :         /* Align to byte boundary before reading raw string data */
     125                 :         927 :         rc = tp_bs_reader_align_to_byte(r);
     126         [ +  + ]:         927 :         if (rc != TP_OK)
     127                 :           1 :             return rc;
     128         [ +  + ]:         926 :         if (base_buf) {
     129                 :             :             const uint8_t *ptr;
     130                 :         925 :             rc = tp_bs_reader_direct_ptr(r, &ptr, (size_t)slen);
     131         [ +  + ]:         925 :             if (rc == TP_OK) {
     132                 :         909 :                 val->data.string_val.str = (const char *)ptr;
     133                 :         909 :                 val->data.string_val.str_len = (size_t)slen;
     134                 :             :             }
     135                 :             :         } else {
     136                 :           1 :             rc = tp_bs_reader_advance(r, slen * 8);
     137                 :           1 :             val->data.string_val.str = NULL;
     138                 :           1 :             val->data.string_val.str_len = (size_t)slen;
     139                 :             :         }
     140                 :         926 :         break;
     141                 :             :     }
     142                 :          18 :     case TP_BLOB: {
     143                 :             :         uint64_t blen;
     144                 :          18 :         rc = tp_bs_read_varint_u(r, &blen);
     145         [ +  + ]:          18 :         if (rc != TP_OK)
     146                 :           3 :             return rc;
     147                 :             :         /* Align to byte boundary before reading raw blob data */
     148                 :          16 :         rc = tp_bs_reader_align_to_byte(r);
     149         [ +  + ]:          16 :         if (rc != TP_OK)
     150                 :           1 :             return rc;
     151         [ +  + ]:          15 :         if (base_buf) {
     152                 :             :             const uint8_t *ptr;
     153                 :          14 :             rc = tp_bs_reader_direct_ptr(r, &ptr, (size_t)blen);
     154         [ +  - ]:          14 :             if (rc == TP_OK) {
     155                 :          14 :                 val->data.blob_val.data = ptr;
     156                 :          14 :                 val->data.blob_val.len = (size_t)blen;
     157                 :             :             }
     158                 :             :         } else {
     159                 :           1 :             rc = tp_bs_reader_advance(r, blen * 8);
     160                 :           1 :             val->data.blob_val.data = NULL;
     161                 :           1 :             val->data.blob_val.len = (size_t)blen;
     162                 :             :         }
     163                 :          15 :         break;
     164                 :             :     }
     165                 :         115 :     case TP_ARRAY:
     166                 :             :     case TP_DICT:
     167                 :         115 :         return TP_ERR_INVALID_PARAM; /* deferred */
     168                 :             :     }
     169                 :    50009419 :     return rc;
     170                 :             : }
        

Generated by: LCOV version 2.0-1