-/* Convert N to a human readable format in BUF.
-
- N is expressed in units of FROM_UNITS; use units of TO_UNITS in the
- output number. FROM_UNITS and TO_UNITS must be positive, and one must
- be a multiple of the other.
-
- If BASE is nonzero, use a format like "127k" if possible,
- using powers of BASE; otherwise, use ordinary decimal format.
- Normally BASE is either 1000 or 1024; it must be at least 2.
- Most people visually process strings of 3-4 digits effectively,
- but longer strings of digits are more prone to misinterpretation.
- Hence, converting to an abbreviated form usually improves readability.
- Use a suffix indicating which power is being used.
- For example, assuming BASE is 1024, 8500 would be converted to 8.3k,
- 133456345 to 127M, 56990456345 to 53G, and so on. Numbers smaller
- than BASE aren't modified. */
+
+/* If INEXACT_STYLE is not human_round_to_nearest, and if easily
+ possible, adjust VALUE according to the style. */
+
+static long double
+adjust_value (int inexact_style, long double value)
+{
+ /* Do not use the floorl or ceill functions, as that would mean
+ checking for their presence and possibly linking with the
+ standard math library, which is a porting pain. So leave the
+ value alone if it is too large to easily round. */
+ if (inexact_style != human_round_to_nearest && value < UINTMAX_MAX)
+ {
+ uintmax_t u = value;
+ value = u + (inexact_style == human_ceiling && u != value);
+ }
+
+ return value;
+}
+
+/* Group the digits of NUMBER according to the grouping rules of the
+ current locale. NUMBER contains NUMBERLEN digits. Modify the
+ bytes pointed to by NUMBER in place, subtracting 1 from NUMBER for
+ each byte inserted. Return the starting address of the modified
+ number.
+
+ To group the digits, use GROUPING and THOUSANDS_SEP as in `struct
+ lconv' from <locale.h>. */
+
+static char *
+group_number (char *number, size_t numberlen,
+ char const *grouping, char const *thousands_sep)
+{
+ register char *d;
+ size_t grouplen = SIZE_MAX;
+ size_t thousands_seplen = strlen (thousands_sep);
+ size_t i = numberlen;
+
+ /* The maximum possible value for NUMBERLEN is the number of digits
+ in the square of the largest uintmax_t, so double the size of
+ uintmax_t before converting to a bound. 302 / 1000 is ceil
+ (log10 (2.0)). Add 1 for integer division truncation. */
+ char buf[2 * sizeof (uintmax_t) * CHAR_BIT * 302 / 1000 + 1];
+
+ memcpy (buf, number, numberlen);
+ d = number + numberlen;
+
+ for (;;)
+ {
+ unsigned char g = *grouping;
+
+ if (g)
+ {
+ grouplen = g < CHAR_MAX ? g : i;
+ grouping++;
+ }
+
+ if (i < grouplen)
+ grouplen = i;
+
+ d -= grouplen;
+ i -= grouplen;
+ memcpy (d, buf + i, grouplen);
+ if (i == 0)
+ return d;
+
+ d -= thousands_seplen;
+ memcpy (d, thousands_sep, thousands_seplen);
+ }
+}
+
+/* Convert N to a human readable format in BUF, using the options OPTS.
+
+ N is expressed in units of FROM_BLOCK_SIZE. FROM_BLOCK_SIZE must
+ be nonnegative.
+
+ Use units of TO_BLOCK_SIZE in the output number. TO_BLOCK_SIZE
+ must be positive.
+
+ Use (OPTS & (human_round_to_nearest | human_floor | human_ceiling))
+ to determine whether to take the ceiling or floor of any result
+ that cannot be expressed exactly.
+
+ If (OPTS & human_group_digits), group the thousands digits
+ according to the locale, e.g., `1,000,000' in an American English
+ locale.
+
+ If (OPTS & human_autoscale), deduce the output block size
+ automatically; TO_BLOCK_SIZE must be 1 but it has no effect on the
+ output. Use powers of 1024 if (OPTS & human_base_1024), and powers
+ of 1000 otherwise. For example, assuming powers of 1024, 8500
+ would be converted to 8.3, 133456345 to 127, 56990456345 to 53, and
+ so on. Numbers smaller than the power aren't modified.
+ human_autoscale is normally used together with human_SI.
+
+ If (OPTS & human_SI), append an SI prefix indicating which power is
+ being used. If in addition (OPTS & human_B), append "B" (if base
+ 1000) or "iB" (if base 1024) to the SI prefix. When ((OPTS &
+ human_SI) && ! (OPTS & human_autoscale)), TO_BLOCK_SIZE must be a
+ power of 1024 or of 1000, depending on (OPTS &
+ human_base_1024). */