logo

utils-extra

Collection of extra tools for Unixes
commit: 9f8c1f1231447c647f08f28e208e28ae047a2cfd
parent 0e654312111bf87a1189d354af1960fec26e746a
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Fri, 15 Mar 2024 11:38:45 +0100

cmd/humanize: Use sscanf and long double for si/iec

Diffstat:

Mcmd/humanize.c40++++++++++++++--------------------------
1 file changed, 14 insertions(+), 26 deletions(-)

diff --git a/cmd/humanize.c b/cmd/humanize.c @@ -4,34 +4,31 @@ #define _POSIX_C_SOURCE 200809L -#include <err.h> // errx #include <errno.h> // EINVAL, ERANGE #include <limits.h> // LLONG_MIN, LLONG_MAX #include <stdbool.h> // bool #include <stdio.h> // fprintf, perror, sscanf -#include <stdlib.h> // strtonum #include <unistd.h> // opt*, getopt -void -dtosi(double num, char *buf, size_t bufsize, bool iec) +static void +human_num(long double num, bool iec) { #define PFX 11 char *si_prefixes[PFX] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"}; char *iec_prefixes[PFX] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"}; - int div = iec ? 1024 : 1000; + unsigned div = iec ? 1024 : 1000; char **prefixes = iec ? iec_prefixes : si_prefixes; unsigned quotient = 0; - while(num > div && quotient < PFX) { num /= div; quotient += 1; } - snprintf(buf, bufsize, "%g %s", num, prefixes[quotient]); + printf("%Lg %s\n", num, prefixes[quotient]); } static void @@ -82,9 +79,7 @@ main(int argc, char *argv[]) for(int argi = 0; argi < argc; argi++) { - const char *errstr = NULL; - char buf[32] = ""; - + // Keep sscanf here for easier error handling, rest being pure math if(time) { int year = 0, month = 0, mday = 0, hour = 0, min = 0, sec = 0; @@ -119,25 +114,18 @@ main(int argc, char *argv[]) continue; } - - errno = 0; - long long n = strtoll(argv[argi], NULL, 10); - if(n == LLONG_MIN) - { - errx(1, "%s is too small", argv[argi]); - } - if(n == LLONG_MAX) - { - errx(1, "%s is too large", argv[argi]); - } - if(errno != 0) + else { - perror("humanize: strtoll"); - } + long double num = 0; - dtosi(n, buf, 32, iec); + if(sscanf(argv[argi], "%Lg", &num) < 1) + { + perror("humanize: sscanf"); + return 1; + } - printf("%s\n", buf); + human_num(num, iec); + } } return 0;