LCOV - code coverage report
Current view: top level - libs/rational/src - rational_itoa.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 39 39
Test Date: 2026-07-12 01:01:34 Functions: 100.0 % 2 2
Branches: 95.5 % 22 21

             Branch data     Line data    Source code
       1                 :             : #include "rational.h"
       2                 :             : #include <errno.h>
       3                 :             : 
       4                 :             : // A utility function to reverse a string
       5                 :          33 : static void reverse(
       6                 :             :         char   str[],
       7                 :             :         size_t length)
       8                 :             : {
       9                 :          33 :         size_t start = 0;
      10                 :          33 :         size_t end = 0;
      11                 :             : 
      12                 :             :         // Guard against empty strings
      13         [ +  - ]:          33 :         if(length > 0)
      14                 :             :         {
      15                 :          33 :                 end = length - 1;
      16                 :             :         }
      17                 :             : 
      18         [ +  + ]:         147 :         while(start < end)
      19                 :             :         {
      20                 :         114 :                 char temp = str[start];
      21                 :         114 :                 str[start] = str[end];
      22                 :         114 :                 str[end] = temp;
      23                 :         114 :                 end--;
      24                 :         114 :                 start++;
      25                 :             :         }
      26                 :          33 : }
      27                 :             : 
      28                 :             : /**
      29                 :             :  * @brief Converts an integer to a string representation
      30                 :             :  *
      31                 :             :  * @param value The integer value to convert
      32                 :             :  * @param str The destination string buffer
      33                 :             :  * @param base The base for conversion (2-36)
      34                 :             :  * @return char* Pointer to the resulting string
      35                 :             :  *
      36                 :             :  * @note The buffer should be large enough to hold the result
      37                 :             :  * @note Supports negative numbers only in base 10
      38                 :             :  * @note For invalid base (not in 2-36), sets errno = EINVAL,
      39                 :             :  *       writes an empty string, and returns str
      40                 :             :  * @note If str is NULL, sets errno = EINVAL and returns NULL
      41                 :             :  */
      42                 :          48 : char *itoa(
      43                 :             :         int          num,
      44                 :             :         char         *str,
      45                 :             :         unsigned int base)
      46                 :             : {
      47                 :          48 :         size_t i = 0;
      48                 :          48 :         bool isNegative = false;
      49                 :             :         unsigned int unum; // Use unsigned int for calculations
      50                 :             : 
      51         [ +  + ]:          48 :         if(str == NULL)
      52                 :             :         {
      53                 :           2 :                 errno = EINVAL;
      54                 :           2 :                 return NULL;
      55                 :             :         }
      56                 :             : 
      57   [ +  +  +  + ]:          46 :         if(base < 2 || base > 36)
      58                 :             :         {
      59                 :           6 :                 errno = EINVAL;
      60                 :           6 :                 str[0] = '\0';
      61                 :           6 :                 return str;
      62                 :             :         }
      63                 :             : 
      64                 :             :         /* Handle 0 explicitly, otherwise empty string is
      65                 :             :          * printed for 0 */
      66         [ +  + ]:          40 :         if(num == 0)
      67                 :             :         {
      68                 :           7 :                 str[i++] = '0';
      69                 :           7 :                 str[i] = '\0';
      70                 :           7 :                 return str;
      71                 :             :         }
      72                 :             : 
      73                 :             :         /* Handle negative numbers */
      74   [ +  +  +  + ]:          33 :         if(num < 0 && base == 10)
      75                 :             :         {
      76                 :             :                 /* The number is negative and we are converting to base 10.
      77                 :             :                  * In this case we want to print a leading '-' sign and work
      78                 :             :                  * with the absolute value of the number. For other bases we
      79                 :             :                  * will treat the value as unsigned and show its bit pattern.
      80                 :             :                  */
      81                 :           5 :                 isNegative = true;
      82                 :             : 
      83                 :             :                 /* IMPORTANT:
      84                 :             :                  * We must NOT write: (unsigned int)(-num)
      85                 :             :                  * because the expression (-num) is evaluated in signed int,
      86                 :             :                  * which is undefined behavior when num == INT_MIN
      87                 :             :                  * (e.g. -2147483648 on a 32-bit system), since +2147483648
      88                 :             :                  * cannot be represented in a signed int.
      89                 :             :                  *
      90                 :             :                  * To avoid this, we first cast num to unsigned int, and only
      91                 :             :                  * then apply the unary minus. The unary minus on an unsigned
      92                 :             :                  * type is well-defined: it performs modular arithmetic
      93                 :             :                  * (2^N - value), so it never overflows.
      94                 :             :                  *
      95                 :             :                  * Example for a 32-bit int:
      96                 :             :                  *   num        = INT_MIN         = -2147483648
      97                 :             :                  *   (unsigned)num = 0x80000000  (2147483648u)
      98                 :             :                  *   -(unsigned)num = 0x80000000 (still 2147483648u)
      99                 :             :                  * This is exactly the magnitude we need for INT_MIN.
     100                 :             :                  */
     101                 :           5 :                 unum = (unsigned int)(-(unsigned int)num);
     102                 :             :         } else {
     103                 :             :                 /* For non-negative numbers, or for any base other than 10,
     104                 :             :                  * we simply convert the value to unsigned.
     105                 :             :                  *
     106                 :             :                  * - If num >= 0, this just gives the same numeric value.
     107                 :             :                  * - If num < 0 and base != 10, the result is the unsigned
     108                 :             :                  *   value modulo 2^N, which is useful for hexadecimal or
     109                 :             :                  *   binary dumps of the underlying representation.
     110                 :             :                  */
     111                 :          28 :                 unum = (unsigned int)num;
     112                 :             :         }
     113                 :             : 
     114                 :             :         /* Process individual digits */
     115         [ +  + ]:         267 :         while(unum != 0)
     116                 :             :         {
     117                 :         234 :                 int rem = (int)(unum % base);
     118         [ +  + ]:         234 :                 str[i++] = (rem > 9) ? (char)(rem - 10 + 'A') : (char)(rem + '0');
     119                 :         234 :                 unum = unum / base;
     120                 :             :         }
     121                 :             : 
     122                 :             :         /* If number is negative, append '-' */
     123         [ +  + ]:          33 :         if(isNegative)
     124                 :             :         {
     125                 :           5 :                 str[i++] = '-';
     126                 :             :         }
     127                 :             : 
     128                 :          33 :         str[i] = '\0'; // Append string terminator
     129                 :             : 
     130                 :             :         // Reverse the string
     131                 :          33 :         reverse(str,i);
     132                 :             : 
     133                 :          33 :         return str;
     134                 :             : }
        

Generated by: LCOV version 2.0-1