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

           Branch data     Line data    Source code
       1                 :            : // Copyright 2019-2026 David Robillard <d@drobilla.net>
       2                 :            : // SPDX-License-Identifier: ISC
       3                 :            : 
       4                 :            : #include "number_utils.h"
       5                 :            : 
       6                 :            : #include "char_utils.h"
       7                 :            : #include "int_math.h"
       8                 :            : #include "result.h"
       9                 :            : 
      10                 :            : #include <exess/exess.h>
      11                 :            : 
      12                 :            : #include <assert.h>
      13                 :            : #include <string.h>
      14                 :            : 
      15                 :            : EXESS_NONBLOCKING size_t
      16                 :     261213 : read_sign(int* const sign, const char* const str)
      17                 :            : {
      18         [ +  + ]:     261213 :   if (*str == '-') {
      19                 :      54413 :     *sign = -1;
      20                 :      54413 :     return 1U;
      21                 :            :   }
      22                 :            : 
      23                 :     206800 :   *sign = 1;
      24         [ +  + ]:     206800 :   return (*str == '+') ? 1U : 0U;
      25                 :            : }
      26                 :            : 
      27                 :            : EXESS_NONBLOCKING ExessResult
      28                 :      28469 : read_two_digit_number(uint8_t* const    out,
      29                 :            :                       const uint8_t     min_value,
      30                 :            :                       const uint8_t     max_value,
      31                 :            :                       const char* const str)
      32                 :            : {
      33                 :            :   // Read digits
      34                 :      28469 :   size_t i = 0;
      35   [ +  +  +  + ]:      85383 :   for (; i < 2 && is_digit(str[i]); ++i) {
      36                 :      56914 :     *out = (uint8_t)((*out * 10) + (str[i] - '0'));
      37                 :            :   }
      38                 :            : 
      39                 :            :   // Ensure there are exactly the expected number of digits
      40         [ +  + ]:      28469 :   if (i != 2) {
      41                 :         16 :     return RESULT(EXESS_EXPECTED_DIGIT, i);
      42                 :            :   }
      43                 :            : 
      44                 :            :   // Ensure value is in range
      45   [ +  +  +  + ]:      28453 :   if (*out < min_value || *out > max_value) {
      46                 :         19 :     return RESULT(EXESS_OUT_OF_RANGE, i);
      47                 :            :   }
      48                 :            : 
      49                 :      28434 :   return RESULT(EXESS_SUCCESS, i);
      50                 :            : }
      51                 :            : 
      52                 :            : EXESS_NONBLOCKING size_t
      53                 :      27308 : write_two_digit_number(const uint8_t value,
      54                 :            :                        const size_t  buf_size,
      55                 :            :                        char* const   buf,
      56                 :            :                        const size_t  i)
      57                 :            : {
      58         [ +  + ]:      27308 :   if (i + 1 < buf_size) {
      59         [ +  + ]:      26992 :     buf[i]     = (char)((value >= 10) ? ('0' + (value / 10)) : '0');
      60                 :      26992 :     buf[i + 1] = (char)('0' + (value % 10));
      61                 :            :   }
      62                 :            : 
      63                 :      27308 :   return 2;
      64                 :            : }
      65                 :            : 
      66                 :            : EXESS_NONBLOCKING size_t
      67                 :       8233 : write_zeros(const size_t n,
      68                 :            :             const size_t buf_size,
      69                 :            :             char* const  buf,
      70                 :            :             const size_t i)
      71                 :            : {
      72         [ -  + ]:       8233 :   assert(i + n < buf_size);
      73                 :            :   (void)buf_size;
      74                 :       8233 :   memset(buf + i, '0', n);
      75                 :       8233 :   return n;
      76                 :            : }
      77                 :            : 
      78                 :            : EXESS_NONBLOCKING ExessResult
      79                 :     206337 : read_digits(uint64_t* const out, const char* const str)
      80                 :            : {
      81                 :            :   // Ensure the first character is a digit
      82                 :     206337 :   size_t i = 0;
      83         [ +  + ]:     206337 :   if (!is_digit(str[i])) {
      84                 :        150 :     return RESULT(EXESS_EXPECTED_DIGIT, i);
      85                 :            :   }
      86                 :            : 
      87                 :            :   // Skip leading zeros
      88         [ +  + ]:     206400 :   while (str[i] == '0') {
      89                 :        213 :     ++i;
      90                 :            :   }
      91                 :            : 
      92                 :            :   // Read digits
      93         [ +  + ]:    1328000 :   for (; is_digit(str[i]); ++i) {
      94                 :    1121816 :     const uint64_t next = (*out * 10U) + (uint64_t)(str[i] - '0');
      95         [ +  + ]:    1121816 :     if (next < *out) {
      96                 :          3 :       *out = 0;
      97                 :          3 :       return RESULT(EXESS_OUT_OF_RANGE, i);
      98                 :            :     }
      99                 :            : 
     100                 :    1121813 :     *out = next;
     101                 :            :   }
     102                 :            : 
     103                 :     206184 :   return RESULT(EXESS_SUCCESS, i);
     104                 :            : }
     105                 :            : 
     106                 :            : EXESS_NONBLOCKING ExessResult
     107                 :     216328 : write_digits(const uint64_t value,
     108                 :            :              const size_t   buf_size,
     109                 :            :              char* const    buf,
     110                 :            :              const size_t   i)
     111                 :            : {
     112                 :     216328 :   const uint8_t n_digits = exess_num_digits(value);
     113         [ +  + ]:     216328 :   if (i + n_digits >= buf_size) {
     114                 :       6247 :     return RESULT(EXESS_NO_SPACE, n_digits);
     115                 :            :   }
     116                 :            : 
     117                 :            :   // Point s to the end
     118                 :     210081 :   char* s = buf + i + n_digits - 1U;
     119                 :            : 
     120                 :            :   // Write integer part (right to left)
     121                 :     210081 :   uint64_t remaining = value;
     122                 :            :   do {
     123                 :    1197896 :     *s-- = (char)('0' + (remaining % 10));
     124         [ +  + ]:    1197896 :   } while ((remaining /= 10) > 0);
     125                 :            : 
     126                 :     210081 :   return RESULT(EXESS_SUCCESS, n_digits);
     127                 :            : }

Generated by: LCOV version 1.16