diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | Versions | 1 | ||||
-rw-r--r-- | include/libutil.h | 22 | ||||
-rw-r--r-- | src/humanize_number.c | 145 |
5 files changed, 178 insertions, 2 deletions
@@ -1,3 +1,10 @@ +2006-08-25 Petr Salinger <Petr.Salinger@seznam.cz> + + * src/humanize_number.c: New file. + * include/libutil.h: New file with humanize_number declarations. + * Makefile (LIB_SRCS): Add humanize_number.c. + * Versions: Add humanize_number. + 2006-03-29 Robert Millan <rmh@aybabtu.com> * src/heapsort.c: New file. @@ -4,12 +4,13 @@ # $Id$ # -LIB_SRCS := arc4random.c bsd_getopt.c err.c fgetln.c heapsort.c inet_net_pton.c \ +LIB_SRCS := arc4random.c bsd_getopt.c err.c fgetln.c heapsort.c \ + humanize_number.c inet_net_pton.c \ strlcat.c strlcpy.c md5c.c fmtcheck.c progname.c vis.c unvis.c LIB_SRCS := $(patsubst %,src/%,$(LIB_SRCS)) LIB_INCLUDES := bsd/err.h bsd/getopt.h bsd/ip_icmp.h bsd/random.h bsd/queue.h bsd/md5.h bsd/string.h \ - bsd/bsd.h bsd/cdefs.h bsd/stdlib.h vis.h + bsd/bsd.h bsd/cdefs.h bsd/stdlib.h vis.h libutil.h LIB_MANS := arc4random.3 strlcpy.3 fgetln.3 fmtcheck.3 LIB_MANS := $(patsubst %,man/%,$(LIB_MANS)) @@ -7,6 +7,7 @@ LIBBSD_0.0 { fgetwln; fmtcheck; heapsort; + humanize_number; inet_net_pton; getprogname; setprogname; strlcpy; diff --git a/include/libutil.h b/include/libutil.h new file mode 100644 index 0000000..4953a65 --- /dev/null +++ b/include/libutil.h @@ -0,0 +1,22 @@ +#ifndef _LIBUTIL_H_ +#define _LIBUTIL_H_ + +#include <features.h> +#include <sys/types.h> + + +__BEGIN_DECLS +int humanize_number(char *buf, size_t len, int64_t bytes, + const char *suffix, int scale, int flags); +__END_DECLS + +/* humanize_number(3) */ +#define HN_DECIMAL 0x01 +#define HN_NOSPACE 0x02 +#define HN_B 0x04 +#define HN_DIVISOR_1000 0x08 + +#define HN_GETSCALE 0x10 +#define HN_AUTOSCALE 0x20 + +#endif /* !_LIBUTIL_H_ */ diff --git a/src/humanize_number.c b/src/humanize_number.c new file mode 100644 index 0000000..bb35550 --- /dev/null +++ b/src/humanize_number.c @@ -0,0 +1,145 @@ +/* $NetBSD: humanize_number.c,v 1.11 2006/06/08 21:08:56 simonb Exp $ */ + +/* + * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include <assert.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> +#include <libutil.h> + +int +humanize_number(char *buf, size_t len, int64_t bytes, + const char *suffix, int scale, int flags) +{ + const char *prefixes, *sep; + int b, i, r, maxscale, s1, s2, sign; + int64_t divisor, max; + size_t baselen; + + assert(buf != NULL); + assert(suffix != NULL); + assert(scale >= 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 { + /* + * binary multiplies + * XXX IEC 60027-2 recommends Ki, Mi, Gi... + */ + divisor = 1024; + if (flags & HN_B) + prefixes = "B\0K\0M\0G\0T\0P\0E"; + else + prefixes = "\0\0K\0M\0G\0T\0P\0E"; + } + +#define SCALE2PREFIX(scale) (&prefixes[(scale) << 1]) + maxscale = 7; + + if (scale >= maxscale && + (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0) + return (-1); + + if (buf == NULL || suffix == NULL) + return (-1); + + if (len > 0) + buf[0] = '\0'; + if (bytes < 0) { + sign = -1; + bytes *= -100; + baselen = 3; /* sign, digit, prefix */ + } else { + sign = 1; + bytes *= 100; + baselen = 2; /* digit, prefix */ + } + if (flags & HN_NOSPACE) + sep = ""; + else { + sep = " "; + baselen++; + } + baselen += strlen(suffix); + + /* Check if enough room for `x y' + suffix + `\0' */ + if (len < baselen + 1) + return (-1); + + if (scale & (HN_AUTOSCALE | HN_GETSCALE)) { + /* See if there is additional columns can be used. */ + for (max = 100, i = len - baselen; i-- > 0;) + max *= 10; + + for (i = 0; bytes >= max && i < maxscale; i++) + bytes /= divisor; + + if (scale & HN_GETSCALE) + return (i); + } else + for (i = 0; i < scale && i < maxscale; i++) + bytes /= divisor; + + /* If a value <= 9.9 after rounding and ... */ + if (bytes < 995 && i > 0 && flags & HN_DECIMAL) { + /* baselen + \0 + .N */ + if (len < baselen + 1 + 2) + return (-1); + b = ((int)bytes + 5) / 10; + s1 = b / 10; + s2 = b % 10; + r = snprintf(buf, len, "%d%s%d%s%s%s", + sign * s1, localeconv()->decimal_point, s2, + sep, SCALE2PREFIX(i), suffix); + } else + r = snprintf(buf, len, "%" PRId64 "%s%s%s", + sign * ((bytes + 50) / 100), + sep, SCALE2PREFIX(i), suffix); + + return (r); +} |