From: Justin Tobler Date: Mon, 15 Dec 2025 20:56:34 GMT Subject: [PATCH v3 2/7] strbuf: split out logic to humanise byte values Message-ID: <20251215205639.2700270-3-jltobler@gmail.com> In-Reply-To: <20251215205639.2700270-1-jltobler@gmail.com> In a subsequent commit, byte size values displayed in table output for the git-repo(1) "structure" subcommand will be shown in a more human-readable format with the appropriate unit prefixes. For this usecase, the downscaled values and unit prefixes must be handled separately to ensure proper column alignment. Split out logic from strbuf_humanise() to downscale byte values and determine the corresponding unit prefix into a separate humanise_bytes() function that provides seperate value and unit strings. Signed-off-by: Justin Tobler --- strbuf.c | 69 ++++++++++++++++++++++++++++---------------------------- strbuf.h | 14 ++++++++++++ 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/strbuf.c b/strbuf.c index 6c3851a7f8..bb8e98872f 100644 --- a/strbuf.c +++ b/strbuf.c @@ -836,47 +836,48 @@ void strbuf_addstr_urlencode(struct strbuf *sb, const char *s, strbuf_add_urlencode(sb, s, strlen(s), allow_unencoded_fn); } -static void strbuf_humanise(struct strbuf *buf, off_t bytes, - int humanise_rate) +void humanise_bytes(off_t bytes, char **value, const char **unit, + unsigned flags) { + int humanise_rate = flags & HUMANISE_RATE; + if (bytes > 1 << 30) { - strbuf_addf(buf, - humanise_rate == 0 ? - /* TRANSLATORS: IEC 80000-13:2008 gibibyte */ - _("%u.%2.2u GiB") : - /* TRANSLATORS: IEC 80000-13:2008 gibibyte/second */ - _("%u.%2.2u GiB/s"), - (unsigned)(bytes >> 30), - (unsigned)(bytes & ((1 << 30) - 1)) / 10737419); + *value = xstrfmt(_("%u.%2.2u"), (unsigned)(bytes >> 30), + (unsigned)(bytes & ((1 << 30) - 1)) / 10737419); + /* TRANSLATORS: IEC 80000-13:2008 gibibyte/second and gibibyte */ + *unit = humanise_rate ? _("GiB/s") : _("GiB"); } else if (bytes > 1 << 20) { - unsigned x = bytes + 5243; /* for rounding */ - strbuf_addf(buf, - humanise_rate == 0 ? - /* TRANSLATORS: IEC 80000-13:2008 mebibyte */ - _("%u.%2.2u MiB") : - /* TRANSLATORS: IEC 80000-13:2008 mebibyte/second */ - _("%u.%2.2u MiB/s"), - x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20); + unsigned x = bytes + 5243; /* for rounding */ + *value = xstrfmt(_("%u.%2.2u"), x >> 20, + ((x & ((1 << 20) - 1)) * 100) >> 20); + /* TRANSLATORS: IEC 80000-13:2008 mebibyte/second and mebibyte */ + *unit = humanise_rate ? _("MiB/s") : _("MiB"); } else if (bytes > 1 << 10) { - unsigned x = bytes + 5; /* for rounding */ - strbuf_addf(buf, - humanise_rate == 0 ? - /* TRANSLATORS: IEC 80000-13:2008 kibibyte */ - _("%u.%2.2u KiB") : - /* TRANSLATORS: IEC 80000-13:2008 kibibyte/second */ - _("%u.%2.2u KiB/s"), - x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10); + unsigned x = bytes + 5; /* for rounding */ + *value = xstrfmt(_("%u.%2.2u"), x >> 10, + ((x & ((1 << 10) - 1)) * 100) >> 10); + /* TRANSLATORS: IEC 80000-13:2008 kibibyte/second and kibibyte */ + *unit = humanise_rate ? _("KiB/s") : _("KiB"); } else { - strbuf_addf(buf, - humanise_rate == 0 ? - /* TRANSLATORS: IEC 80000-13:2008 byte */ - Q_("%u byte", "%u bytes", bytes) : - /* TRANSLATORS: IEC 80000-13:2008 byte/second */ - Q_("%u byte/s", "%u bytes/s", bytes), - (unsigned)bytes); + *value = xstrfmt(_("%u"), (unsigned)bytes); + *unit = humanise_rate ? + /* TRANSLATORS: IEC 80000-13:2008 byte/second */ + Q_("byte/s", "bytes/s", bytes) : + /* TRANSLATORS: IEC 80000-13:2008 byte */ + Q_("byte", "bytes", bytes); } } +static void strbuf_humanise(struct strbuf *buf, off_t bytes, unsigned flags) +{ + char *value; + const char *unit; + + humanise_bytes(bytes, &value, &unit, flags); + strbuf_addf(buf, _("%s %s"), value, unit); + free(value); +} + void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes) { strbuf_humanise(buf, bytes, 0); @@ -884,7 +885,7 @@ void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes) void strbuf_humanise_rate(struct strbuf *buf, off_t bytes) { - strbuf_humanise(buf, bytes, 1); + strbuf_humanise(buf, bytes, HUMANISE_RATE); } int printf_ln(const char *fmt, ...) diff --git a/strbuf.h b/strbuf.h index a580ac6084..4426163e7e 100644 --- a/strbuf.h +++ b/strbuf.h @@ -367,6 +367,20 @@ void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src); */ void strbuf_add_percentencode(struct strbuf *dst, const char *src, int flags); +enum humanise_flags { + /* + * Use rate based unit prefixes for humanised values. + */ + HUMANISE_RATE = (1 << 0), +}; + +/** + * Converts the given byte size into a downscaled human-readable value and + * corresponding unit prefix as two separate strings. + */ +void humanise_bytes(off_t bytes, char **value, const char **unit, + unsigned flags); + /** * Append the given byte size as a human-readable string (i.e. 12.23 KiB, * 3.50 MiB). -- 2.52.0.209.ge85ae279b0