Home | History | Annotate | Download | only in lib
      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  */
     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