NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: lib/60635: humanize_number(3): exa/exbi issues



# HG changeset patch
# User Taylor R Campbell <riastradh%NetBSD.org@localhost>
# Date 1787506011 0
#      Sun Aug 23 17:26:51 2026 +0000
# Branch trunk
# Node ID cc8c7b6b7bd389ee5f3db6fdd197869e8577a0cd
# Parent  6f8d3c18f5e5266c57e1b8b3736224c0146f1726
# EXP-Topic riastradh-pr59411-prgrowingnowaitcleanup
humanize_number(3): New option HN_IEC for IEC prefixes.

PR lib/60635: humanize_number(3): exa/exbi issues

diff -r 6f8d3c18f5e5 -r cc8c7b6b7bd3 lib/libc/gen/humanize_number.3
--- a/lib/libc/gen/humanize_number.3	Sun Aug 23 16:54:15 2026 +0000
+++ b/lib/libc/gen/humanize_number.3	Sun Aug 23 17:26:51 2026 +0000
@@ -61,20 +61,52 @@ would be too long to fit into
 .Fa buffer ,
 then repeatedly divide
 .Fa number
-by 1024 until it will fit.
+by a base, either 1024 (default) or 1000 (decimal, with
+.Dv HN_DIVISOR_1000 ) ,
+until it will fit.
 In this case, prefix
 .Fa suffix
-with the appropriate SI designator.
+with the corresponding scale designator.
+.Pp
+For the default binary base (1024), the prefixes are:
+.Bl -column "Prefix" "IEC" "Name" "Multiplier" -offset indent
+.It Sy "Prefix" Ta Sy "IEC" Ta Sy "Name" Ta Sy "Multiplier"
+.It K	Ki	kibi	1,024
+.It M	Mi	mebi	1,048,576
+.It G	Gi	gibi	1,073,741,824
+.It T	Ti	tebi	1,099,511,627,776
+.It P	Pi	pebi	1,125,899,906,842,624
+.It E	Ei	exbi	1,152,921,504,606,846,976
+.El
 .Pp
-The prefixes are:
-.Bl -column "Prefix" "Description" "Multiplier" -offset indent
-.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
-.It k	kilo	1024
-.It M	mega	1048576
-.It G	giga	1073741824
-.It T	tera	1099511627776
-.It P	peta	1125899906842624
-.It E	exa	1152921504606846976
+The nonstandard
+.Dq Tn SI
+or
+.Tn JEDEC Ns No - Ns style
+prefixes
+.Dq K ,
+.Dq M ,
+etc., are chosen by default.
+The
+.Tn IEC
+prefixes
+.Dq Ki ,
+.Dq Mi ,
+etc., are chosen by the
+.Dv HN_IEC
+option.
+.Pp
+For the decimal base (1000, chosen by
+.Dv HN_DIVISOR_1000 ) ,
+the SI prefixes are:
+.Bl -column "Prefix" "Name" "Multiplier" -offset indent
+.It Sy "Prefix" Ta Sy "Name" Ta Sy "Multiplier"
+.It k	kilo	1,000
+.It M	mega	1,000,000
+.It G	giga	1,000,000,000
+.It T	tera	1,000,000,000,000
+.It P	peta	1,000,000,000,000,000
+.It E	exa	1,000,000,000,000,000,000
 .El
 .Pp
 .Fa len
@@ -123,6 +155,17 @@ Divide
 .Fa number
 with 1000 instead of 1024.
 That is, use decimal scaling instead of binary.
+.Pp
+Exclusive with
+.Dv HN_IEC .
+.It Dv HN_IEC
+Use IEC prefixes
+.Dq Ki ,
+.Dq Mi ,
+etc.
+.Pp
+Exclusive with
+.Dv HN_DIVISOR_1000 .
 .El
 .Pp
 To generate the shortest meaningful value,
diff -r 6f8d3c18f5e5 -r cc8c7b6b7bd3 lib/libc/gen/humanize_number.c
--- a/lib/libc/gen/humanize_number.c	Sun Aug 23 16:54:15 2026 +0000
+++ b/lib/libc/gen/humanize_number.c	Sun Aug 23 17:26:51 2026 +0000
@@ -52,9 +52,12 @@ humanize_number(char *buf, size_t len, i
 	int64_t	divisor, max, post = 1;
 	size_t	baselen;
 	int	maxscale;
+	int	prefixbytes = 1;
 
 	_DIAGASSERT(buf != NULL);
 	_DIAGASSERT(scale >= 0);
+	_DIAGASSERT((flags & (HN_DIVISOR_1000|HN_IEC)) !=
+	    (HN_DIVISOR_1000|HN_IEC));
 
 	if (suffix == NULL)
 		suffix = "";
@@ -68,17 +71,31 @@ humanize_number(char *buf, size_t len, i
 			prefixes = "\0\0k\0M\0G\0T\0P\0E";
 	} else {
 		/*
-		 * binary multiplies
-		 * XXX IEC 60027-2 recommends Ki, Mi, Gi...
+		 * binary multiplies with `SI'/JEDEC-style or IEC
+		 * prefixes
 		 */
 		divisor = 1024;
-		if (flags & HN_B)
+		switch (flags & (HN_B|HN_IEC)) {
+		case HN_B:
 			prefixes = "B\0K\0M\0G\0T\0P\0E";
-		else
+			break;
+		case 0:
 			prefixes = "\0\0K\0M\0G\0T\0P\0E";
+			break;
+		case HN_B|HN_IEC:
+			prefixes = "B\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+			prefixbytes = 2;
+			break;
+		case HN_IEC:
+			prefixes = "\0\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+			prefixbytes = 2;
+			break;
+		default:
+			__unreachable();
+		}
 	}
 
-#define	SCALE2PREFIX(scale)	(&prefixes[(scale) << 1])
+#define	SCALE2PREFIX(scale)	(&prefixes[(scale) * (prefixbytes + 1)])
 	maxscale = 6;
 
 	if (scale < 0 || (scale > maxscale &&
diff -r 6f8d3c18f5e5 -r cc8c7b6b7bd3 tests/lib/libc/gen/t_humanize_number.c
--- a/tests/lib/libc/gen/t_humanize_number.c	Sun Aug 23 16:54:15 2026 +0000
+++ b/tests/lib/libc/gen/t_humanize_number.c	Sun Aug 23 17:26:51 2026 +0000
@@ -112,6 +112,32 @@ const struct hnopts {
 	  NULL },
 	{ 4, 1024LL*1024*1024*1024*1024*1024, "", HN_AUTOSCALE, HN_B, 3, "1 E",
 	  "PR lib/60635: humanize_number(3): exa/exbi issues" },
+
+	{ 5, 1, "", HN_AUTOSCALE, HN_IEC, 2, "1 ", NULL },
+	{ 5, 1024LL, "", HN_AUTOSCALE, HN_IEC, 4, "1 Ki", NULL },
+	{ 5, 1024LL*1024, "", HN_AUTOSCALE, HN_IEC, 4, "1 Mi", NULL },
+	{ 5, 1024LL*1024*1024, "", HN_AUTOSCALE, HN_IEC, 4, "1 Gi", NULL },
+	{ 5, 1024LL*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC, 4, "1 Ti",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC, 4, "1 Pi",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024*1024*1024, "", HN_AUTOSCALE,HN_IEC, 4,
+	  "1 Ei",
+	  "PR lib/60635: humanize_number(3): exa/exbi issues" },
+
+	{ 5, 1, "", HN_AUTOSCALE, HN_IEC|HN_B, 3, "1 B", NULL },
+	{ 5, 1024LL, "", HN_AUTOSCALE, HN_IEC|HN_B, 4, "1 Ki", NULL },
+	{ 5, 1024LL*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4, "1 Mi", NULL },
+	{ 5, 1024LL*1024*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4, "1 Gi",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4, "1 Ti",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4,
+	  "1 Pi",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4,
+	  "1 Ei",
+	  "PR lib/60635: humanize_number(3): exa/exbi issues" },
 };
 
 struct hnflags {


Home | Main Index | Thread Index | Old Index