num2str: add arguments to represent values in terms of bytes/bits
[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, int unit_base)
9 {
10         const char *postfix[] = { "", "K", "M", "G", "P", "E" };
11         const char *byte_postfix[] = { "", "B", "bit" };
12         const unsigned int thousand[] = { 1000, 1024 };
13         unsigned int modulo, decimals;
14         int byte_post_index = 0, post_index, carry = 0;
15         char tmp[32];
16         char *buf;
17
18         buf = malloc(128);
19
20         for (post_index = 0; base > 1; post_index++)
21                 base /= thousand[!!pow2];
22
23         switch (unit_base) {
24         case 1:
25                 byte_post_index = 2;
26                 num *= 8;
27                 break;
28         case 8:
29                 byte_post_index = 1;
30                 break;
31         }
32
33         modulo = -1U;
34         while (post_index < sizeof(postfix)) {
35                 sprintf(tmp, "%lu", num);
36                 if (strlen(tmp) <= maxlen)
37                         break;
38
39                 modulo = num % thousand[!!pow2];
40                 num /= thousand[!!pow2];
41                 carry = modulo >= thousand[!!pow2] / 2;
42                 post_index++;
43         }
44
45         if (modulo == -1U) {
46 done:
47                 sprintf(buf, "%lu%s%s", num, postfix[post_index],
48                         byte_postfix[byte_post_index]);
49                 return buf;
50         }
51
52         sprintf(tmp, "%lu", num);
53         decimals = maxlen - strlen(tmp);
54         if (decimals <= 1) {
55                 if (carry)
56                         num++;
57                 goto done;
58         }
59
60         do {
61                 sprintf(tmp, "%u", modulo);
62                 if (strlen(tmp) <= decimals - 1)
63                         break;
64
65                 modulo = (modulo + 9) / 10;
66         } while (1);
67
68         sprintf(buf, "%lu.%u%s%s", num, modulo, postfix[post_index],
69                 byte_postfix[byte_post_index]);
70         return buf;
71 }