num2str fixes
[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, carry = 0;
14         char tmp[32];
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                 carry = modulo >= thousand[!!pow2] / 2;
31                 post_index++;
32         }
33
34         if (modulo == -1U) {
35 done:
36                 sprintf(buf, "%lu%c", num, postfix[post_index]);
37                 return buf;
38         }
39
40         sprintf(tmp, "%lu", num);
41         decimals = maxlen - strlen(tmp);
42         if (decimals <= 1) {
43                 if (carry)
44                         num++;
45                 goto done;
46         }
47
48         do {
49                 sprintf(tmp, "%u", modulo);
50                 if (strlen(tmp) <= decimals - 1)
51                         break;
52
53                 modulo = (modulo + 9) / 10;
54         } while (1);
55
56         sprintf(buf, "%lu.%u%c", num, modulo, postfix[post_index]);
57         return buf;
58 }