blob: 559cbeb590e4926b2d34f3b34cf6ac4cc0eadf10 [file] [log] [blame]
Jens Axboe1ec3d692010-09-16 09:35:34 +02001#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4
5/*
6 * Cheesy number->string conversion, complete with carry rounding error.
7 */
8char *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;
Jens Axboe05463812010-09-16 14:56:23 +020013 int post_index, carry = 0;
14 char tmp[32];
Jens Axboe1ec3d692010-09-16 09:35:34 +020015 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];
Jens Axboe05463812010-09-16 14:56:23 +020030 carry = modulo >= thousand[!!pow2] / 2;
Jens Axboe1ec3d692010-09-16 09:35:34 +020031 post_index++;
32 }
33
34 if (modulo == -1U) {
35done:
36 sprintf(buf, "%lu%c", num, postfix[post_index]);
37 return buf;
38 }
39
40 sprintf(tmp, "%lu", num);
41 decimals = maxlen - strlen(tmp);
Jens Axboe05463812010-09-16 14:56:23 +020042 if (decimals <= 1) {
43 if (carry)
44 num++;
Jens Axboe1ec3d692010-09-16 09:35:34 +020045 goto done;
Jens Axboe05463812010-09-16 14:56:23 +020046 }
Jens Axboe1ec3d692010-09-16 09:35:34 +020047
Jens Axboe05463812010-09-16 14:56:23 +020048 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]);
Jens Axboe1ec3d692010-09-16 09:35:34 +020057 return buf;
58}