X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fhuman.c;h=6d91b8c1b7f00012484d2a46b822c6dab86cc74a;hb=98a354147cdb6d15365600fac33d492d7387996f;hp=f7dcdfb2a890ba63acf4e5459d9310f416eb5c07;hpb=f8715f3aef61f46759c775b99f25c8726267b2ac;p=gnulib.git diff --git a/lib/human.c b/lib/human.c index f7dcdfb2a..6d91b8c1b 100644 --- a/lib/human.c +++ b/lib/human.c @@ -23,10 +23,6 @@ # include #endif -#if HAVE_INTTYPES_H -# include -#endif - #include #include @@ -34,6 +30,12 @@ # include #endif +#if HAVE_STRING_H +# include +#else +# include +#endif + #ifndef CHAR_BIT # define CHAR_BIT 8 #endif @@ -54,7 +56,7 @@ char *getenv (); #include #include -#include +#include #include "human.h" @@ -71,15 +73,27 @@ static const char suffixes[] = 'Y' /* Yotta */ }; +/* Like human_readable_inexact, except always round to even. */ +char * +human_readable (uintmax_t n, char *buf, + int from_block_size, int output_block_size) +{ + return human_readable_inexact (n, buf, from_block_size, output_block_size, + human_round_to_even); +} + /* Convert N to a human readable format in BUF. N is expressed in units of FROM_BLOCK_SIZE. FROM_BLOCK_SIZE must - be positive. + be nonnegative. If OUTPUT_BLOCK_SIZE is positive, use units of OUTPUT_BLOCK_SIZE in the output number. OUTPUT_BLOCK_SIZE must be a multiple of FROM_BLOCK_SIZE or vice versa. + Use INEXACT_STYLE to determine whether to take the ceiling or floor + of any result that cannot be expressed exactly. + If OUTPUT_BLOCK_SIZE is negative, use a format like "127k" if possible, using powers of -OUTPUT_BLOCK_SIZE; otherwise, use ordinary decimal format. Normally -OUTPUT_BLOCK_SIZE is either @@ -93,13 +107,14 @@ static const char suffixes[] = than -OUTPUT_BLOCK_SIZE aren't modified. */ char * -human_readable (uintmax_t n, char *buf, - int from_block_size, int output_block_size) +human_readable_inexact (uintmax_t n, char *buf, + int from_block_size, int output_block_size, + enum human_inexact_style inexact_style) { uintmax_t amt; int base; int to_block_size; - int tenths; + int tenths = 0; int power; char *p; @@ -107,7 +122,7 @@ human_readable (uintmax_t n, char *buf, 1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05; 2 means adjusted N == AMT.TENTHS + 0.05; 3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */ - int rounding; + int rounding = 0; if (output_block_size < 0) { @@ -134,7 +149,6 @@ human_readable (uintmax_t n, char *buf, { int multiplier = from_block_size / to_block_size; amt = n * multiplier; - tenths = rounding = 0; if (amt / multiplier != n) { @@ -170,6 +184,8 @@ human_readable (uintmax_t n, char *buf, return buf; } } + else if (from_block_size == 0) + amt = 0; else { int divisor = to_block_size / from_block_size; @@ -204,24 +220,33 @@ human_readable (uintmax_t n, char *buf, if (amt < 10) { - tenths += 2 < rounding + (tenths & 1); - - if (tenths == 10) + if (2 * (1 - (int) inexact_style) + < rounding + (tenths & (inexact_style == human_round_to_even))) { - amt++; - tenths = 0; + tenths++; + rounding = 0; + + if (tenths == 10) + { + amt++; + tenths = 0; + } } if (amt < 10) { *--p = '0' + tenths; *--p = '.'; - tenths = 0; + tenths = rounding = 0; } } } - if (5 < tenths + (2 < rounding + (amt & 1))) + if (inexact_style == human_ceiling + ? 0 < tenths + rounding + : inexact_style == human_round_to_even + ? 5 < tenths + (2 < rounding + (amt & 1)) + : /* inexact_style == human_floor */ 0) { amt++;