commit: 950e3a9c99ff0d965077b3013783a3612d7d7b38
parent b989ec55d65529f5dfa16db56374e337f0b30a7e
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sun, 8 May 2022 19:38:35 +0200
bin/humanize: drop humanize_number, roll own algorithm
Diffstat:
3 files changed, 55 insertions(+), 47 deletions(-)
diff --git a/bin/humanize.1 b/bin/humanize.1
@@ -1,7 +1,7 @@
.\" Collection of Unix tools, comparable to coreutils
.\" Copyright 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
.\" SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
-.Dd 2021-05-13
+.Dd 2022-05-08
.Dt HUMANIZE 1
.Os
.Sh NAME
@@ -14,7 +14,7 @@
.Sh DESCRIPTION
Takes each
.Ar number
-and format it in a human readable form.
+and format it in a human readable form, one per line.
It supports the following options:
.Bl -tag -width Ds
.It Fl b
@@ -24,7 +24,5 @@ Divide by 1000, this is the default but made explicit in case of changes without
.El
.Sh EXIT STATUS
.Ex -std
-.Sh SEE ALSO
-.Xr humanize_number 3
.Sh AUTHORS
.An Haelwenn (lanodan) Monnier Aq Mt contact@hacktivis.me
diff --git a/bin/humanize.c b/bin/humanize.c
@@ -6,15 +6,36 @@
// strtonum
#define _OPENBSD_SOURCE
// On non-BSDs use libbsd
-#include <err.h> // errx
-#include <errno.h> // EINVAL, ERANGE
-#include <limits.h> // LLONG_MIN, LLONG_MAX
-#include <stdio.h> // fprintf
-#include <stdlib.h> // humanize_number, strtonum
-#include <string.h> // strerror
-#include <unistd.h> // opt*, getopt
+#include <err.h> // errx
+#include <errno.h> // EINVAL, ERANGE
+#include <limits.h> // LLONG_MIN, LLONG_MAX
+#include <stdbool.h> // bool
+#include <stdio.h> // fprintf
+#include <stdlib.h> // strtonum
+#include <string.h> // strerror
+#include <unistd.h> // opt*, getopt
void
+dtosi(double num, char *buf, size_t bufsize, bool iec)
+{
+ char *si_prefixes[9] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y"};
+ char *iec_prefixes[9] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"};
+
+ int div = iec ? 1024 : 1000;
+ char **prefixes = iec ? iec_prefixes : si_prefixes;
+
+ unsigned quotient = 0;
+
+ while(num > div && quotient < 9)
+ {
+ num /= div;
+ quotient += 1;
+ }
+
+ snprintf(buf, bufsize, "%g %s", num, prefixes[quotient]);
+}
+
+static void
usage()
{
fprintf(stderr, "Usage: humanize [-bd] number\n");
@@ -23,23 +44,19 @@ usage()
int
main(int argc, char *argv[])
{
- int c;
- int flags = HN_NOSPACE | HN_DECIMAL;
// default to -d
- int divisor = HN_DIVISOR_1000;
- size_t buflen = 6;
+ bool iec = false;
+ int c = -1;
while((c = getopt(argc, argv, ":bd")) != -1)
{
switch(c)
{
case 'b':
- divisor = ~HN_DIVISOR_1000;
- buflen = 7; // 4 digits, 3 letters for suffix, NUL byte
+ iec = true;
break;
case 'd':
- divisor = HN_DIVISOR_1000;
- buflen = 6; // 4 digits, 2 letters for suffix, NUL byte
+ iec = false;
break;
case ':':
fprintf(stderr, "Error: Missing operand for option: '-%c'\n", optopt);
@@ -64,7 +81,7 @@ main(int argc, char *argv[])
for(int argi = 0; argi < argc; argi++)
{
const char *errstr = NULL;
- char buffer[7] = "-";
+ char buf[32] = "";
// 1024^(6+1) goes higher than long long; don't ask for the moon
long long n = strtonum(argv[argi], LLONG_MIN, LLONG_MAX, &errstr);
@@ -73,17 +90,10 @@ main(int argc, char *argv[])
errx(1, "strtonum: %s is %s", argv[argi], errstr);
}
- int err = humanize_number(buffer, buflen, n, "", HN_AUTOSCALE, flags | divisor);
- if(err < 0)
- {
- fprintf(stderr, "humanize_number: %s is %s\n", argv[argi], strerror(errno));
- return 1;
- }
+ dtosi(n, buf, 32, iec);
- printf("%s ", buffer);
+ printf("%s\n", buf);
}
- printf("\n");
-
return 0;
}
diff --git a/test-bin/humanize b/test-bin/humanize
@@ -3,53 +3,53 @@ atf_test_case one
one_body() {
atf_check -o "inline:1 \n" ../bin/humanize 1
atf_check -o "inline:1 \n" ../bin/humanize -d 1
- atf_check -o "inline:1B \n" ../bin/humanize -b 1
+ atf_check -o "inline:1 B\n" ../bin/humanize -b 1
}
atf_test_case two
two_body() {
atf_check -o "inline:12 \n" ../bin/humanize 12
atf_check -o "inline:12 \n" ../bin/humanize -d 12
- atf_check -o "inline:12B \n" ../bin/humanize -b 12
+ atf_check -o "inline:12 B\n" ../bin/humanize -b 12
}
atf_test_case three
three_body() {
atf_check -o "inline:123 \n" ../bin/humanize 123
atf_check -o "inline:123 \n" ../bin/humanize -d 123
- atf_check -o "inline:123B \n" ../bin/humanize -b 123
+ atf_check -o "inline:123 B\n" ../bin/humanize -b 123
}
# 1 234
atf_test_case four
four_body() {
- atf_check -o "inline:1234 \n" ../bin/humanize 1234
- atf_check -o "inline:1234 \n" ../bin/humanize -d 1234
- atf_check -o "inline:1234B \n" ../bin/humanize -b 1234
+ atf_check -o "inline:1.234 k\n" ../bin/humanize 1234
+ atf_check -o "inline:1.234 k\n" ../bin/humanize -d 1234
+ atf_check -o "inline:1.20508 KiB\n" ../bin/humanize -b 1234
}
# 12 345
atf_test_case five
five_body() {
- atf_check -o "inline:12k \n" ../bin/humanize 12345
- atf_check -o "inline:12k \n" ../bin/humanize -d 12345
- atf_check -o "inline:12Ki \n" ../bin/humanize -b 12345
+ atf_check -o "inline:12.345 k\n" ../bin/humanize 12345
+ atf_check -o "inline:12.345 k\n" ../bin/humanize -d 12345
+ atf_check -o "inline:12.0557 KiB\n" ../bin/humanize -b 12345
}
# 123 456
atf_test_case six
six_body() {
- atf_check -o "inline:123k \n" ../bin/humanize 123456
- atf_check -o "inline:123k \n" ../bin/humanize -d 123456
- atf_check -o "inline:121Ki \n" ../bin/humanize -b 123456
+ atf_check -o "inline:123.456 k\n" ../bin/humanize 123456
+ atf_check -o "inline:123.456 k\n" ../bin/humanize -d 123456
+ atf_check -o "inline:120.562 KiB\n" ../bin/humanize -b 123456
}
# 1234 4567
atf_test_case seven
seven_body() {
- atf_check -o "inline:1235k \n" ../bin/humanize 1234567
- atf_check -o "inline:1235k \n" ../bin/humanize -d 1234567
- atf_check -o "inline:1206Ki \n" ../bin/humanize -b 1234567
+ atf_check -o "inline:1.23457 M\n" ../bin/humanize 1234567
+ atf_check -o "inline:1.23457 M\n" ../bin/humanize -d 1234567
+ atf_check -o "inline:1.17737 MiB\n" ../bin/humanize -b 1234567
}
atf_test_case noarg
@@ -65,11 +65,11 @@ badflag_body() {
atf_test_case limits
limits_body() {
- atf_check -o 'inline:9223P \n' ../bin/humanize 9223372036854775807
+ atf_check -o 'inline:9.22337 E\n' ../bin/humanize 9223372036854775807
atf_check -s exit:1 -e 'inline:humanize: strtonum: 9223372036854775808 is too large\n' ../bin/humanize 9223372036854775808
- # The fuck is this result
- atf_check -o 'inline:-9223 \n' ../bin/humanize -- -9223372036854775808
+ # Not as great as it should but at least not a lie
+ atf_check -o 'inline:-9.22337e+18 \n' ../bin/humanize -- -9223372036854775808
atf_check -s exit:1 -e 'inline:humanize: strtonum: -9223372036854775809 is too small\n' ../bin/humanize -- -9223372036854775809
}