Implement a better num2str()
[fio.git] / lib / num2str.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 /*
6  * Cheesy number->string conversion, complete with carry rounding error.
7  */
8 char *num2str(unsigned long num, int maxlen, int base, int pow2)
9 {
10         char postfix[] = { ' ', 'K', 'M', 'G', 'P', 'E' };
11         unsigned int thousand[] = { 1000, 1024 };
12         unsigned int modulo, decimals;
13         int post_index;
14         char tmp[32], fmt[8];
15         char *buf;
16
17         buf = malloc(128);
18
19         for (post_index = 0; base > 1; post_index++)
20                 base /= thousand[!!pow2];
21
22         modulo = -1U;
23         while (post_index < sizeof(postfix)) {
24                 sprintf(tmp, "%lu", num);
25                 if (strlen(tmp) <= maxlen)
26                         break;
27
28                 modulo = num % thousand[!!pow2];
29                 num /= thousand[!!pow2];
30                 post_index++;
31         }
32
33         if (modulo == -1U) {
34 done:
35                 sprintf(buf, "%lu%c", num, postfix[post_index]);
36                 return buf;
37         }
38
39         sprintf(tmp, "%lu", num);
40         decimals = maxlen - strlen(tmp);
41         if (decimals <= 1)
42                 goto done;
43
44         sprintf(fmt, "%%.%uu", decimals - 1);
45         sprintf(tmp, fmt, modulo);
46         sprintf(buf, "%lu.%s%c", num, tmp, postfix[post_index]);
47         return buf;
48 }