LCOV - code coverage report
Current view: top level - libs/rational/src - rational_form.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 79.4 % 34 27
Test Date: 2026-01-12 05:34:38 Functions: 100.0 % 1 1

            Line data    Source code
       1              : #include "rational.h"
       2              : 
       3              : #define PRINT_CHECKOUT 0
       4              : 
       5              : /**
       6              :  *
       7              :  * @brief Locale-aware format 1234567.89 -> 1,234,567.89
       8              :  * @details va_arg format got from https://stackoverflow.com/a/23647983/7104681
       9              :  * and https://stackoverflow.com/questions/1449805/how-to-format-a-number-using-comma-as-thousands-separator-in-c
      10              :  * @param val - Any long double digit
      11              :  * @return Pointer to a string
      12              :  *
      13              :  */
      14           15 : const char *form(long double val)
      15              : {
      16              :         static char result[MAX_CHARACTERS];
      17           15 :         result[0] = '\0';  /* Initialize buffer as empty string */
      18              : 
      19              :         // Compare the argument passed to the parent function
      20              :         // with zero accurate to 10 digits and output zero
      21           15 :         if(fabsl(val) < 0.0000000001L)
      22              :         {
      23            6 :                 result[0] = '0';
      24            6 :                 result[1] = '\0';
      25            6 :                 return result;
      26              :         }
      27              : 
      28            9 :         snprintf(result,sizeof(result),"%.9Lf",val);
      29            9 :         char *pt = NULL;
      30              : 
      31              :         // Point pt at "."
      32           30 :         for(pt = result; *pt && *pt != '.'; pt++)
      33              :         {
      34              :                 #if PRINT_CHECKOUT
      35              :                 printf("pt: %p, pt addr: %zu\n",(void *)pt,(void *)pt);
      36              :                 #endif
      37              :         }
      38              : 
      39              :         /*
      40              :          * Adding a thousand separator
      41              :          *
      42              :          */
      43              : 
      44              :         // Length of fractional part
      45            9 :         size_t n = (size_t)result + sizeof(result) - (size_t)pt - 1;
      46              :         #if PRINT_CHECKOUT
      47              :         printf("n: %zu\n",n);
      48              :         #endif
      49              : 
      50              :         // Step backwards, inserting spaces
      51              :         while(true)
      52            2 :         {
      53           11 :                 if(pt <= result + 3)
      54              :                 {
      55            9 :                         break;
      56              :                 }
      57              : 
      58            2 :                 char *insertion_point = pt - 3; // shift 3 digits
      59              : 
      60            2 :                 if(*(insertion_point-1) == '-')
      61              :                 {
      62            0 :                         break;
      63              :                 }
      64              : 
      65            2 :                 memmove(insertion_point + 1,insertion_point,n);
      66              :                 #if PRINT_CHECKOUT
      67              :                 printf("pt: %p, pt addr: %zu\n",(void *)insertion_point,(void *)insertion_point);
      68              :                 #endif
      69              :                 // memmove allows overlap, unlike memcpy
      70            2 :                 *insertion_point = ','; // thousand separator
      71            2 :                 n += 4; // 3 digits + separator
      72            2 :                 pt = insertion_point;
      73              :         }
      74              : 
      75              :         #if PRINT_CHECKOUT
      76              :         printf("n: %zu\n",n);
      77              :         #endif
      78              : 
      79            9 :         char *ptr = strchr(result,'.');
      80              :         #if PRINT_CHECKOUT
      81              :         printf("ptr: %p, ptr addr: %zu\n",(void *)ptr,(void *)ptr);
      82              :         #endif
      83              : 
      84            9 :         if(ptr!=NULL)
      85              :         {
      86              :                 // Either val is real or integer
      87            9 :                 bool val_is_real = false;
      88              : 
      89           90 :                 for(pt = ptr+1; pt < (result + sizeof(result)) && *pt != '\0'; pt++)
      90              :                 {
      91           81 :                         if(*pt != '0')
      92              :                         {
      93            0 :                                 val_is_real = true;
      94            0 :                                 break;
      95              :                         }
      96              :                 }
      97              : 
      98            9 :                 if(val_is_real)
      99              :                 {
     100            0 :                         *ptr = '.';
     101              : 
     102              :                         // Remove unnecessary terminated zeroes
     103            0 :                         for(pt = (result + sizeof(result)) - 1; pt >= ptr; --pt)
     104              :                         {
     105              :                                 #if PRINT_CHECKOUT
     106              :                                 printf("pt: %p, pt addr: %zu, ptr: %p, ptr addr: %zu\n",(void *)pt,(void *)pt,(void *)ptr,(void *)ptr);
     107              :                                 #endif
     108              : 
     109            0 :                                 if(*pt == '\0' || *pt == '0' || *pt == ',')
     110              :                                 {
     111            0 :                                         *pt = '\0';
     112              :                                 } else {
     113              :                                         break;
     114              :                                 }
     115              :                         }
     116              :                         #if 0
     117              :                         printf("\n");
     118              :                         #endif
     119              :                 } else {
     120            9 :                         *ptr = '\0';
     121              :                 }
     122              :         }
     123              : 
     124            9 :         return(result);
     125              : }
     126              : 
     127              : // Test
     128              : #if 0
     129              : int main(void)
     130              : {
     131              :         double digit = 837452834.94;
     132              :         printf("digit: %s\n",form(digit));
     133              : }
     134              : #endif
        

Generated by: LCOV version 2.0-1