humanize.c (2855B)
- // Collection of Unix tools, comparable to coreutils
- // SPDX-FileCopyrightText: 2017-2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #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)
- {
- #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;
- 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]);
- }
- static void
- usage()
- {
- fprintf(stderr, "Usage: humanize [-bdt] number\n");
- }
- int
- main(int argc, char *argv[])
- {
- // default to -d
- bool iec = false, time = false;
- int c = -1;
- while((c = getopt(argc, argv, ":bdt")) != -1)
- {
- switch(c)
- {
- case 'b':
- iec = true;
- break;
- case 'd':
- iec = false;
- break;
- case 't':
- time = true;
- break;
- case ':':
- fprintf(stderr, "humanize: Error: Missing operand for option: '-%c'\n", optopt);
- usage();
- return 1;
- case '?':
- fprintf(stderr, "humanize: Error: Unrecognised option: '-%c'\n", optopt);
- usage();
- return 1;
- }
- }
- argc -= optind;
- argv += optind;
- if(argc < 1)
- {
- usage();
- return 1;
- }
- for(int argi = 0; argi < argc; argi++)
- {
- const char *errstr = NULL;
- char buf[32] = "";
- if(time)
- {
- int year = 0, month = 0, mday = 0, hour = 0, min = 0, sec = 0;
- long int epoch = 0;
- if(sscanf(argv[argi], "%ld", &epoch) < 1)
- {
- perror("humanize: sscanf");
- return 1;
- }
- year = epoch / 31556926; // round(year)
- epoch %= 31556926;
- month = epoch / 2629743; // year/12
- epoch %= 2629743;
- mday = epoch / 86400;
- epoch %= 86400;
- hour = epoch / 3600;
- epoch %= 3600;
- min = epoch / 60;
- epoch %= 60;
- sec = epoch;
- if(year > 0) printf("%d年 ", year);
- if(month > 0) printf("%d月 ", month);
- if(mday > 0) printf("%d日 ", mday);
- if(hour > 0) printf("%dh ", hour);
- if(min > 0) printf("%dm ", min);
- if(sec > 0) printf("%ds", sec);
- printf("\n");
- 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)
- {
- perror("humanize: strtoll");
- }
- dtosi(n, buf, 32, iec);
- printf("%s\n", buf);
- }
- return 0;
- }