Author: delphij
Date: Tue Apr 12 22:48:03 2011
New Revision: 220582
URL: http://svn.freebsd.org/changeset/base/220582

Log:
  Add support for IEE/IEC (and now also SI) power of two notions of
  prefixes (Ki, Mi, Gi...) for humanize_number(3).
  
  Note that applications has to pass HN_IEC_PREFIXES to use this
  feature for backward compatibility reasons.
  
  Reviewed by:  arundel
  MFC after:    2 weeks

Modified:
  head/lib/libutil/humanize_number.3
  head/lib/libutil/humanize_number.c
  head/lib/libutil/libutil.h

Modified: head/lib/libutil/humanize_number.3
==============================================================================
--- head/lib/libutil/humanize_number.3  Tue Apr 12 22:41:52 2011        
(r220581)
+++ head/lib/libutil/humanize_number.3  Tue Apr 12 22:48:03 2011        
(r220582)
@@ -28,7 +28,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd May 25, 2004
+.Dd Apr 12, 2011
 .Dt HUMANIZE_NUMBER 3
 .Os
 .Sh NAME
@@ -68,17 +68,24 @@ then divide
 by 1024 until it will.
 In this case, prefix
 .Fa suffix
-with the appropriate SI designator.
+with the appropriate designator.
 The
 .Fn humanize_number
-function
-follows the traditional computer science conventions rather than the proposed
-SI power of two convention.
+function follows the traditional computer science conventions by
+default, rather than the IEE/IEC (and now also SI) power of two
+convention or the power of ten notion.
+This behaviour however can be altered by specifying the
+.Dv HN_DIVISOR_1000
+and
+.Dv HN_IEC_PREFIXES
+flags.
 .Pp
-The prefixes are:
+The traditional
+.Pq default
+prefixes are:
 .Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
 .It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier" Ta Sy "Multiplier 1000x"
-.It Li k Ta No kilo Ta 1024 Ta 1000
+.It Li (note) Ta No kilo Ta 1024 Ta 1000
 .It Li M Ta No mega Ta 1048576 Ta 1000000
 .It Li G Ta No giga Ta 1073741824 Ta 1000000000
 .It Li T Ta No tera Ta 1099511627776 Ta 1000000000000
@@ -86,6 +93,20 @@ The prefixes are:
 .It Li E Ta No exa Ta 1152921504606846976 Ta 1000000000000000000
 .El
 .Pp
+Note:
+An uppercase K indicates a power of two, a lowercase k a power of ten.
+.Pp
+The IEE/IEC (and now also SI) power of two prefixes are:
+.Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
+.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
+.It Li Ki Ta No kibi Ta 1024
+.It Li Mi Ta No mebi Ta 1048576
+.It Li Gi Ta No gibi Ta 1073741824
+.It Li Ti Ta No tebi Ta 1099511627776
+.It Li Pi Ta No pebi Ta 1125899906842624
+.It Li Ei Ta No exbi Ta 1152921504606846976
+.El
+.Pp
 The
 .Fa len
 argument must be at least 4 plus the length of
@@ -94,7 +115,12 @@ in order to ensure a useful result is ge
 .Fa buf .
 To use a specific prefix, specify this as
 .Fa scale
-(multiplier = 1024 ^ scale).
+.Po multiplier = 1024 ^ scale;
+when
+.Dv HN_DIVISOR_1000
+is specified,
+multiplier = 1000 ^ scale
+.Pc .
 This cannot be combined with any of the
 .Fa scale
 flags below.
@@ -127,6 +153,11 @@ Use
 Divide
 .Fa number
 with 1000 instead of 1024.
+.It Dv HN_IEC_PREFIXES
+Use the IEE/IEC notion of prefixes (Ki, Mi, Gi...).
+This flag has no effect when
+.Dv HN_DIVISOR_1000
+is also specified.
 .El
 .Sh RETURN VALUES
 The
@@ -141,6 +172,18 @@ If
 is specified, the prefix index number will be returned instead.
 .Sh SEE ALSO
 .Xr expand_number 3
+.Sh STANDARDS
+The
+.Dv HN_DIVISOR_1000
+and
+.Dv HN_IEC_PREFIXES
+flags
+conform to
+.Tn ISO/IEC
+Std\~80000-13:2008
+and
+.Tn IEEE
+Std\~1541-2002.
 .Sh HISTORY
 The
 .Fn humanize_number
@@ -148,3 +191,7 @@ function first appeared in
 .Nx 2.0
 and then in
 .Fx 5.3 .
+The
+.Dv HN_IEC_PREFIXES
+flag was introduced in
+.Fx 9.0 .

Modified: head/lib/libutil/humanize_number.c
==============================================================================
--- head/lib/libutil/humanize_number.c  Tue Apr 12 22:41:52 2011        
(r220581)
+++ head/lib/libutil/humanize_number.c  Tue Apr 12 22:48:03 2011        
(r220582)
@@ -42,45 +42,58 @@ __FBSDID("$FreeBSD$");
 #include <locale.h>
 #include <libutil.h>
 
+static const int maxscale = 7;
+
 int
 humanize_number(char *buf, size_t len, int64_t quotient,
     const char *suffix, int scale, int flags)
 {
        const char *prefixes, *sep;
-       int     i, r, remainder, maxscale, s1, s2, sign;
+       int     i, r, remainder, s1, s2, sign;
        int64_t divisor, max;
        size_t  baselen;
 
        assert(buf != NULL);
        assert(suffix != NULL);
        assert(scale >= 0);
+       assert(scale < maxscale || (((scale & (HN_AUTOSCALE | HN_GETSCALE)) != 
0)));
+       assert(!((flags & HN_DIVISOR_1000) && (flags & HN_IEC_PREFIXES)));
 
        remainder = 0;
 
-       if (flags & HN_DIVISOR_1000) {
-               /* SI for decimal multiplies */
-               divisor = 1000;
-               if (flags & HN_B)
-                       prefixes = "B\0k\0M\0G\0T\0P\0E";
-               else
-                       prefixes = "\0\0k\0M\0G\0T\0P\0E";
-       } else {
+       if (flags & HN_IEC_PREFIXES) {
+               baselen = 2;
                /*
-                * binary multiplies
-                * XXX IEC 60027-2 recommends Ki, Mi, Gi...
+                * Use the prefixes for power of two recommended by
+                * the International Electrotechnical Commission
+                * (IEC) in IEC 80000-3 (i.e. Ki, Mi, Gi...).
+                *
+                * HN_IEC_PREFIXES implies a divisor of 1024 here
+                * (use of HN_DIVISOR_1000 would have triggered
+                * an assertion earlier).
                 */
                divisor = 1024;
                if (flags & HN_B)
-                       prefixes = "B\0K\0M\0G\0T\0P\0E";
+                       prefixes = "B\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+               else
+                       prefixes = "\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+       } else {
+               baselen = 1;
+               if (flags & HN_DIVISOR_1000)
+                       divisor = 1000;
+               else
+                       divisor = 1024;
+
+               if (flags & HN_B)
+                       prefixes = "B\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
                else
-                       prefixes = "\0\0K\0M\0G\0T\0P\0E";
+                       prefixes = "\0\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
        }
 
-#define        SCALE2PREFIX(scale)     (&prefixes[(scale) << 1])
-       maxscale = 7;
+#define        SCALE2PREFIX(scale)     (&prefixes[(scale) * 3])
 
-       if (scale >= maxscale &&
-           (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
+       if (scale < 0 || (scale >= maxscale &&
+           (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0))
                return (-1);
 
        if (buf == NULL || suffix == NULL)
@@ -91,10 +104,10 @@ humanize_number(char *buf, size_t len, i
        if (quotient < 0) {
                sign = -1;
                quotient = -quotient;
-               baselen = 3;            /* sign, digit, prefix */
+               baselen += 2;           /* sign, digit */
        } else {
                sign = 1;
-               baselen = 2;            /* digit, prefix */
+               baselen += 1;           /* digit */
        }
        if (flags & HN_NOSPACE)
                sep = "";

Modified: head/lib/libutil/libutil.h
==============================================================================
--- head/lib/libutil/libutil.h  Tue Apr 12 22:41:52 2011        (r220581)
+++ head/lib/libutil/libutil.h  Tue Apr 12 22:48:03 2011        (r220582)
@@ -220,7 +220,9 @@ __END_DECLS
 #define HN_NOSPACE             0x02
 #define HN_B                   0x04
 #define HN_DIVISOR_1000                0x08
+#define HN_IEC_PREFIXES                0x10
 
+/* maxscale = 0x07 */
 #define HN_GETSCALE            0x10
 #define HN_AUTOSCALE           0x20
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to