Subject: bin/15508: humanize_number(3)
To: None <gnats-bugs@gnats.netbsd.org>
From: Tomas Svensson <tsn@gbdev.net>
List: netbsd-bugs
Date: 02/06/2002 15:14:21
>Number: 15508
>Category: bin
>Synopsis: humanize_number(3)
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Wed Feb 06 07:16:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:
>Release: NetBSD 1.5ZA
>Organization:
>Environment:
NetBSD 1.5ZA
>Description:
Here is a new version of humanize_number(9) for libc to be used
in programs such as df(1)/du(1)/ls(1).
Differences from the kernel version are:
- the bytes argument is signed (negative sizes can be used).
- the divisor argument is replaced with a flag, see below.
- rounding is done like floating point numbers were used.
- the suffix-prefix K is changed to k, which should be correct
according to standards.
- three flags can be used : HN_DECIMAL tells it to use one decimal
for numbers less than 10, HN_NOSPACE removes the space between
the number and the prefix, HN_DIVISOR_1000 makes the divisor
1000 (otherwise 1024 is assumed) and HN_B will use the prefix "B" for
numbers that would normally not have a prefix (bytes less than
1000). Use 0 if no flags are used (not worth the trouble with
varargs?).
>How-To-Repeat:
>Fix:
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#define HN_DECIMAL 1
#define HN_NOSPACE 2
#define HN_B 4
#define HN_DIVISOR_1000 8
int humanize_number(char *, size_t, int64_t, const char *, int);
int humanize_number(char *buf, size_t len, int64_t bytes,
const char *suffix, int flags) {
static const char prefixes[] = " kMGTPE";
int divisor, i, r;
int64_t max, s1, s2, sign;
size_t baselen, suffixlen;
if (buf == NULL)
return -1;
if (len > 0)
buf[0] = '\0';
if (bytes < 0) {
sign = -1;
bytes *= -100;
baselen = 4;
} else {
sign = 1;
bytes *= 100;
baselen = 3;
}
suffixlen = strlen(suffix);
/* check if enough room for `x y' + suffix + `\0' */
if (len < baselen + suffixlen + 1)
return (-1);
if (flags & HN_DIVISOR_1000)
divisor = 1000;
else
divisor = 1024;
max = 100;
for (i = 0; i < len - suffixlen - baselen + ((flags & HN_NOSPACE) ?
1 : 0) ; i++)
max *= 10;
for (i = 0; bytes >= max && i < sizeof(prefixes); i++)
bytes /= divisor;
if (bytes < 1000 && flags & HN_DECIMAL) {
if (len < (baselen + 2 + ( (flags & HN_NOSPACE) || (i == 0 &&
!(flags & HN_B)) ? 0 : 1)))
return (-1);
s1 = bytes / 100;
if ((s2 = (( (bytes % 100 ) + 5 ) / 10 ) ) == 10 ) {
s1++;
s2 = 0;
}
r = snprintf(buf, len, "%qd%s%qd%s%c%s", sign * s1,
localeconv()->decimal_point, s2,
(i == 0 && !(flags & HN_B) ) || flags & HN_NOSPACE ?
"" : " ", (i == 0 && (flags & HN_B)) ? 'B' :
prefixes[i], suffix);
} else
r = snprintf(buf, len, "%qd%s%c%s", sign * ((bytes + 50) / 100),
i == 0 || flags & HN_NOSPACE ? "" : " ", (i == 0 &&
(flags & HN_B)) ? 'B' : prefixes[i], suffix);
return r;
}
>Release-Note:
>Audit-Trail:
>Unformatted: