LCOV - code coverage report
Current view: top level - src - hex.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 44 44 100.0 %
Date: 2026-07-14 21:28:07 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 30 30 100.0 %

           Branch data     Line data    Source code
       1                 :            : // Copyright 2011-2026 David Robillard <d@drobilla.net>
       2                 :            : // SPDX-License-Identifier: ISC
       3                 :            : 
       4                 :            : #include "char_utils.h"
       5                 :            : #include "read_utils.h"
       6                 :            : #include "result.h"
       7                 :            : #include "write_utils.h"
       8                 :            : 
       9                 :            : #include <exess/exess.h>
      10                 :            : 
      11                 :            : #include <stdint.h>
      12                 :            : #include <string.h>
      13                 :            : 
      14                 :            : /// Hex encoding table
      15                 :            : static const char hex_map[] = "0123456789ABCDEF";
      16                 :            : 
      17                 :            : static uint8_t
      18                 :      65547 : decode_nibble(const char c)
      19                 :            : {
      20         [ +  + ]:      65547 :   if (is_digit(c)) {
      21                 :      41022 :     return (uint8_t)(c - '0');
      22                 :            :   }
      23                 :            : 
      24   [ +  +  +  + ]:      24525 :   if (c >= 'A' && c <= 'F') {
      25                 :      24505 :     return (uint8_t)(10 + c - 'A');
      26                 :            :   }
      27                 :            : 
      28   [ +  +  +  + ]:         20 :   if (c >= 'a' && c <= 'f') {
      29                 :          6 :     return (uint8_t)(10 + c - 'a');
      30                 :            :   }
      31                 :            : 
      32                 :         14 :   return UINT8_MAX;
      33                 :            : }
      34                 :            : 
      35                 :            : EXESS_NONBLOCKING size_t
      36                 :          6 : exess_decoded_hex_size(const size_t length)
      37                 :            : {
      38                 :          6 :   return length / 2;
      39                 :            : }
      40                 :            : 
      41                 :            : EXESS_NONBLOCKING ExessVariableResult
      42                 :        316 : exess_read_hex(const char* const str, const size_t out_size, void* const out)
      43                 :            : {
      44                 :        316 :   uint8_t* const uout  = (uint8_t*)out;
      45                 :        316 :   const size_t   first = skip_whitespace(str);
      46                 :        316 :   size_t         i     = first;
      47                 :        316 :   size_t         o     = 0U;
      48                 :            : 
      49         [ +  + ]:      33079 :   while (str[i]) {
      50                 :      32778 :     const char    hi_char = str[i];
      51                 :      32778 :     const uint8_t hi      = decode_nibble(hi_char);
      52         [ +  + ]:      32778 :     if (hi == UINT8_MAX) {
      53         [ +  + ]:          8 :       return VRESULT(i == first ? EXESS_EXPECTED_HEX : EXESS_SUCCESS, i, o);
      54                 :            :     }
      55                 :            : 
      56                 :      32770 :     ++i;
      57                 :            : 
      58                 :      32770 :     const char lo_char = str[i];
      59         [ +  + ]:      32770 :     if (!lo_char) {
      60                 :          1 :       return VRESULT(EXESS_EXPECTED_HEX, i, o);
      61                 :            :     }
      62                 :            : 
      63                 :      32769 :     const uint8_t lo = decode_nibble(lo_char);
      64         [ +  + ]:      32769 :     if (lo == UINT8_MAX) {
      65                 :          6 :       return VRESULT(EXESS_EXPECTED_HEX, i, o);
      66                 :            :     }
      67                 :            : 
      68                 :      32763 :     ++i;
      69                 :            : 
      70         [ +  + ]:      32763 :     if (o < out_size) {
      71                 :      32757 :       uout[o] = (uint8_t)(((unsigned)hi << 4U) | lo);
      72                 :            :     }
      73                 :            : 
      74                 :      32763 :     ++o;
      75                 :            :   }
      76                 :            : 
      77         [ +  + ]:        301 :   return VRESULT(o <= out_size ? EXESS_SUCCESS : EXESS_NO_SPACE, i, o);
      78                 :            : }
      79                 :            : 
      80                 :            : EXESS_NONBLOCKING ExessResult
      81                 :        519 : exess_write_hex(const size_t      data_size,
      82                 :            :                 const void* const data,
      83                 :            :                 const size_t      buf_size,
      84                 :            :                 char* const       buf)
      85                 :            : {
      86                 :        519 :   const size_t length = 2 * data_size;
      87   [ +  +  +  + ]:        519 :   if (!buf || length >= buf_size) {
      88                 :        261 :     return end_write(EXESS_NO_SPACE, buf_size, buf, length);
      89                 :            :   }
      90                 :            : 
      91                 :        258 :   const uint8_t* const in = (const uint8_t*)data;
      92                 :        258 :   size_t               o  = 0U;
      93                 :            : 
      94         [ +  + ]:      32907 :   for (size_t i = 0; i < data_size; ++i) {
      95                 :      32649 :     const uint8_t hi = (in[i] & 0xF0U) >> 4U;
      96                 :      32649 :     const uint8_t lo = (in[i] & 0x0FU);
      97                 :            : 
      98                 :      32649 :     buf[o++] = hex_map[hi];
      99                 :      32649 :     buf[o++] = hex_map[lo];
     100                 :            :   }
     101                 :            : 
     102                 :        258 :   return end_write(EXESS_SUCCESS, buf_size, buf, o);
     103                 :            : }

Generated by: LCOV version 1.16