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 % 30 30
Test Date: 2026-01-12 05:34:38 Functions: 100.0 % 2 2

            Line data    Source code
       1              : #include "rational.h"
       2              : 
       3              : // A utility function to reverse a string
       4           20 : static void reverse(
       5              :         char   str[],
       6              :         size_t length)
       7              : {
       8           20 :         size_t start = 0;
       9           20 :         size_t end = length > 0 ? length - 1 : 0;  // Guard against empty strings
      10              : 
      11           86 :         while(start < end)
      12              :         {
      13           66 :                 char temp = str[start];
      14           66 :                 str[start] = str[end];
      15           66 :                 str[end] = temp;
      16           66 :                 end--;
      17           66 :                 start++;
      18              :         }
      19           20 : }
      20              : 
      21              : /**
      22              :  * @brief Converts an integer to a string representation
      23              :  *
      24              :  * @param value The integer value to convert
      25              :  * @param str The destination string buffer
      26              :  * @param base The base for conversion (2-36)
      27              :  * @return char* Pointer to the resulting string
      28              :  *
      29              :  * @note The buffer should be large enough to hold the result
      30              :  * @note Supports negative numbers only in base 10
      31              :  */
      32           24 : char *itoa(
      33              :         int          num,
      34              :         char         *str,
      35              :         unsigned int base)
      36              : {
      37           24 :         size_t i = 0;
      38           24 :         bool isNegative = false;
      39              :         unsigned int unum; // Use unsigned int for calculations
      40              : 
      41              :         /* Handle 0 explicitly, otherwise empty string is
      42              :          * printed for 0 */
      43           24 :         if(num == 0)
      44              :         {
      45            4 :                 str[i++] = '0';
      46            4 :                 str[i] = '\0';
      47            4 :                 return str;
      48              :         }
      49              : 
      50              :         /* Handle negative numbers */
      51           20 :         if(num < 0 && base == 10)
      52              :         {
      53              :                 /* The number is negative and we are converting to base 10.
      54              :                  * In this case we want to print a leading '-' sign and work
      55              :                  * with the absolute value of the number. For other bases we
      56              :                  * will treat the value as unsigned and show its bit pattern.
      57              :                  */
      58            4 :                 isNegative = true;
      59              : 
      60              :                 /* IMPORTANT:
      61              :                  * We must NOT write: (unsigned int)(-num)
      62              :                  * because the expression (-num) is evaluated in signed int,
      63              :                  * which is undefined behavior when num == INT_MIN
      64              :                  * (e.g. -2147483648 on a 32-bit system), since +2147483648
      65              :                  * cannot be represented in a signed int.
      66              :                  *
      67              :                  * To avoid this, we first cast num to unsigned int, and only
      68              :                  * then apply the unary minus. The unary minus on an unsigned
      69              :                  * type is well-defined: it performs modular arithmetic
      70              :                  * (2^N - value), so it never overflows.
      71              :                  *
      72              :                  * Example for a 32-bit int:
      73              :                  *   num        = INT_MIN         = -2147483648
      74              :                  *   (unsigned)num = 0x80000000  (2147483648u)
      75              :                  *   -(unsigned)num = 0x80000000 (still 2147483648u)
      76              :                  * This is exactly the magnitude we need for INT_MIN.
      77              :                  */
      78            4 :                 unum = (unsigned int)(-(unsigned int)num);
      79              :         } else {
      80              :                 /* For non-negative numbers, or for any base other than 10,
      81              :                  * we simply reinterpret the value as unsigned.
      82              :                  *
      83              :                  * - If num >= 0, this just gives the same numeric value.
      84              :                  * - If num < 0 and base != 10, the bit pattern of num is
      85              :                  *   reinterpreted as an unsigned integer, which allows us
      86              :                  *   to display its two's-complement representation (e.g. for
      87              :                  *   hexadecimal or binary dumps).
      88              :                  */
      89           16 :                 unum = (unsigned int)num;
      90              :         }
      91              : 
      92              :         /* Process individual digits */
      93          154 :         while(unum != 0)
      94              :         {
      95          134 :                 int rem = (int)(unum % base);
      96          134 :                 str[i++] = (rem > 9) ? (char)(rem - 10 + 'A') : (char)(rem + '0');
      97          134 :                 unum = unum / base;
      98              :         }
      99              : 
     100              :         /* If number is negative, append '-' */
     101           20 :         if(isNegative)
     102              :         {
     103            4 :                 str[i++] = '-';
     104              :         }
     105              : 
     106           20 :         str[i] = '\0'; // Append string terminator
     107              : 
     108              :         // Reverse the string
     109           20 :         reverse(str,i);
     110              : 
     111           20 :         return str;
     112              : }
     113              : 
     114              : #if 0
     115              : #include <limits.h>
     116              : /// Test
     117              : 
     118              : static void test_conversion(
     119              :         int          value,
     120              :         unsigned int base,
     121              :         const char   *string)
     122              : {
     123              :         char buffer[66];  /* 64 bits + sign + null terminator */
     124              :         itoa(value,buffer,base);
     125              : 
     126              :         /* Print original value in decimal and result in specified base */
     127              :         printf("Value: %d (decimal)\n",value);
     128              :         printf("Base %2d result: %s, %s\n",base,buffer,string);
     129              :         printf("-------------------\n");
     130              : }
     131              : 
     132              : /**
     133              :  * @brief Test program for itoa function
     134              :  *
     135              :  * @note Tests edge cases and different bases with special focus on
     136              :  *       negative numbers and MIN/MAX integer values
     137              :  */
     138              : static void test_itoa(void)
     139              : {
     140              : 
     141              :         /* Test extreme values */
     142              :         printf("=== Testing extreme values ===\n");
     143              :         test_conversion(INT_MAX,10,"2147483647");
     144              :         test_conversion(INT_MIN,10,"-2147483648");
     145              :         test_conversion(INT_MIN,16,"Should show in hex");
     146              : 
     147              :         /* Test regular cases */
     148              :         printf("\n=== Testing regular values ===\n");
     149              :         test_conversion(255,16,"FF");
     150              :         test_conversion(255,2,"11111111");
     151              :         test_conversion(-255,10,"-255");
     152              : 
     153              :         /* Test zero handling */
     154              :         printf("\n=== Testing zero ===\n");
     155              :         test_conversion(0,10,"0");
     156              :         test_conversion(0,16,"0");
     157              :         test_conversion(0,2,"0");
     158              : 
     159              :         /* Test larger bases */
     160              :         printf("\n=== Testing different bases ===\n");
     161              :         test_conversion(12345,36,"Maximum supported base");
     162              :         test_conversion(12345,16,"Common hex value");
     163              :         test_conversion(12345,8,"Octal");
     164              : 
     165              :         /* Test negative values in different bases */
     166              :         printf("\n=== Testing negative values ===\n");
     167              :         test_conversion(-12345,10,"Only base 10 shows negative sign");
     168              :         test_conversion(-12345,16,"Should show unsigned hex");
     169              :         test_conversion(-1,2,"All bits set");
     170              : 
     171              :         printf("\n=== Few more examples ===\n");
     172              :         char buffer[33];  /* Buffer for 32-bit integer */
     173              : 
     174              :         /* Decimal conversion */
     175              :         itoa(12345,buffer,10);
     176              :         puts(buffer);
     177              : 
     178              :         /* Hexadecimal conversion */
     179              :         itoa(255,buffer,16);
     180              :         puts(buffer);
     181              : 
     182              :         /* Binary conversion */
     183              :         itoa(15,buffer,2);
     184              :         puts(buffer);
     185              : 
     186              :         /* Negative number */
     187              :         itoa(-789,buffer,10);
     188              :         puts(buffer);
     189              : 
     190              :         /* Zero case */
     191              :         itoa(0,buffer,10);
     192              :         puts(buffer);
     193              : 
     194              :         char str[100];
     195              :         printf("Number: %d\nBase: %d\tConverted String: %s\n",1567,10,itoa(1567,str,10));
     196              :         printf("Base: %d\t\tConverted String: %s\n",2,itoa(1567,str,2));
     197              :         printf("Base: %d\t\tConverted String: %s\n",8,itoa(1567,str,8));
     198              :         printf("Base: %d\tConverted String: %s\n",16,itoa(1567,str,16));
     199              : }
     200              : 
     201              : /**
     202              :  * @brief Test program for itoa function
     203              :  *
     204              :  * @note Tests edge cases and different bases with special focus on
     205              :  *       negative numbers and MIN/MAX integer values
     206              :  */
     207              : int main(void)
     208              : {
     209              :         test_itoa();
     210              : 
     211              :         return 0; // Success
     212              : }
     213              : #endif
        

Generated by: LCOV version 2.0-1