1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 
5 #include "../fio.h"
6 
7 #define ARRAY_LENGTH(arr)	sizeof(arr) / sizeof((arr)[0])
8 
9 /*
10  * Cheesy number->string conversion, complete with carry rounding error.
11  */
num2str(uint64_t num,int maxlen,int base,int pow2,int unit_base)12 char *num2str(uint64_t num, int maxlen, int base, int pow2, int unit_base)
13 {
14 	const char *postfix[] = { "", "K", "M", "G", "P", "E" };
15 	const char *byte_postfix[] = { "", "B", "bit" };
16 	const unsigned int thousand[] = { 1000, 1024 };
17 	unsigned int modulo, decimals;
18 	int byte_post_index = 0, post_index, carry = 0;
19 	char tmp[32];
20 	char *buf;
21 
22 	buf = malloc(128);
23 
24 	for (post_index = 0; base > 1; post_index++)
25 		base /= thousand[!!pow2];
26 
27 	switch (unit_base) {
28 	case 1:
29 		byte_post_index = 2;
30 		num *= 8;
31 		break;
32 	case 8:
33 		byte_post_index = 1;
34 		break;
35 	}
36 
37 	modulo = -1U;
38 	while (post_index < sizeof(postfix)) {
39 		sprintf(tmp, "%llu", (unsigned long long) num);
40 		if (strlen(tmp) <= maxlen)
41 			break;
42 
43 		modulo = num % thousand[!!pow2];
44 		num /= thousand[!!pow2];
45 		carry = modulo >= thousand[!!pow2] / 2;
46 		post_index++;
47 	}
48 
49 	if (modulo == -1U) {
50 done:
51 		if (post_index >= ARRAY_LENGTH(postfix))
52 			post_index = 0;
53 
54 		sprintf(buf, "%llu%s%s", (unsigned long long) num,
55 			postfix[post_index], byte_postfix[byte_post_index]);
56 		return buf;
57 	}
58 
59 	sprintf(tmp, "%llu", (unsigned long long) num);
60 	decimals = maxlen - strlen(tmp);
61 	if (decimals <= 1) {
62 		if (carry)
63 			num++;
64 		goto done;
65 	}
66 
67 	do {
68 		sprintf(tmp, "%u", modulo);
69 		if (strlen(tmp) <= decimals - 1)
70 			break;
71 
72 		modulo = (modulo + 9) / 10;
73 	} while (1);
74 
75 	sprintf(buf, "%llu.%u%s%s", (unsigned long long) num, modulo,
76 			postfix[post_index], byte_postfix[byte_post_index]);
77 	return buf;
78 }
79