Module Name: src Committed By: erh Date: Tue Mar 15 03:47:04 UTC 2011
Modified Files: src/lib/libc/gen: Makefile.inc Added Files: src/lib/libc/gen: commaize_number.3 commaize_number.c Log Message: PR#7540, add a commaize_number function, which inserts comma into a string of digits to make it more readable. This is soon to be used in /bin/ls. To generate a diff of this commit: cvs rdiff -u -r1.174 -r1.175 src/lib/libc/gen/Makefile.inc cvs rdiff -u -r0 -r1.1 src/lib/libc/gen/commaize_number.3 \ src/lib/libc/gen/commaize_number.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/gen/Makefile.inc diff -u src/lib/libc/gen/Makefile.inc:1.174 src/lib/libc/gen/Makefile.inc:1.175 --- src/lib/libc/gen/Makefile.inc:1.174 Sat Mar 12 19:52:48 2011 +++ src/lib/libc/gen/Makefile.inc Tue Mar 15 03:47:04 2011 @@ -1,11 +1,12 @@ -# $NetBSD: Makefile.inc,v 1.174 2011/03/12 19:52:48 christos Exp $ +# $NetBSD: Makefile.inc,v 1.175 2011/03/15 03:47:04 erh Exp $ # from: @(#)Makefile.inc 8.6 (Berkeley) 5/4/95 # gen sources .PATH: ${ARCHDIR}/gen ${.CURDIR}/gen SRCS+= _errno.c alarm.c alphasort.c arc4random.c assert.c basename.c clock.c \ - closedir.c closefrom.c confstr.c ctermid.c ctype_.c daemon.c \ + closedir.c closefrom.c commaize_number.c \ + confstr.c ctermid.c ctype_.c daemon.c \ dehumanize_number.c devname.c dirname.c disklabel.c err.c errx.c \ errlist.c errno.c execl.c execle.c execlp.c execv.c execvp.c \ extattr.c fmtcheck.c fmtmsg.c fnmatch.c fstab.c ftok.c \ @@ -50,7 +51,8 @@ .include "${ARCHDIR}/gen/Makefile.inc" -MAN+= alarm.3 arc4random.3 basename.3 bswap.3 clock.3 closefrom.3 confstr.3 \ +MAN+= alarm.3 arc4random.3 basename.3 bswap.3 clock.3 closefrom.3 \ + commaize_number.3 confstr.3 \ cpuset.3 ctermid.3 ctype.3 daemon.3 devname.3 directory.3 dirname.3 \ endutxent.3 err.3 exec.3 extattr.3 \ fmtcheck.3 fmtmsg.3 fnmatch.3 fpclassify.3 fpgetmask.3 \ Added files: Index: src/lib/libc/gen/commaize_number.3 diff -u /dev/null src/lib/libc/gen/commaize_number.3:1.1 --- /dev/null Tue Mar 15 03:47:04 2011 +++ src/lib/libc/gen/commaize_number.3 Tue Mar 15 03:47:04 2011 @@ -0,0 +1,83 @@ +.\" $NetBSD: commaize_number.3,v 1.1 2011/03/15 03:47:04 erh Exp $ +.\" +.\" Copyright (c) 2011 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Eric Haszlakiewicz. +.\" +.\" 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. +.\" +.\" 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. +.\" +.Dd March 12, 2011 +.Dt COMMAIZE_NUMBER 3 +.Os +.Sh NAME +.Nm commaize_number +.Nd format a number into a human readable form by adding commas (actually, the locale specific thousands separator) +.Sh SYNOPSIS +.In stdlib.h +.Ft int +.Fn commaize_number "char *buffer" "size_t len" "int64_t number" +.Sh DESCRIPTION +The +.Fn commaize_number +function formats the signed 64 bit quantity given in +.Fa number +into +.Fa buffer , +which +must be at least +.Fa len +bytes long. +.Pp +If the formatted number would be too long to fit into +.Fa buffer , +then an error is returned. +.Sh RETURN VALUES +.Fn commaize_number +returns the number of characters stored in +.Fa buffer +(excluding the terminating NUL) upon success, or \-1 upon failure with +.Va errno +set to indicate the error. +.Sh ERRORS +.Fn commaize_number +will fail and nothing will be written to +.Fa buffer +if: +.Bl -tag -width Er +.It Bq Er ENOMEM +The formatted number, including commas and terminating NUL, is too long to fit in +.Fa len +bytes. +.El +.Sh SEE ALSO +.Xr humanize_number 9 , +.Xr setlocale 3 , +.Xr ls 1 . +.Sh HISTORY +.Fn humanize_number +first appeared in +.Nx 6.0 . +.Pp +.Sh AUTHORS +.An Eric Haszlakiewicz Aq e...@netbsd.org Index: src/lib/libc/gen/commaize_number.c diff -u /dev/null src/lib/libc/gen/commaize_number.c:1.1 --- /dev/null Tue Mar 15 03:47:04 2011 +++ src/lib/libc/gen/commaize_number.c Tue Mar 15 03:47:04 2011 @@ -0,0 +1,101 @@ +/* $NetBSD: commaize_number.c,v 1.1 2011/03/15 03:47:04 erh Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Eric Haszlakiewicz. + * + * 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. + * + * 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 <errno.h> +#include <inttypes.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +/** + * Format a number with commas (or another locale specific separator) between + * every three digits. + * + * Uses localeconv to figure out which separator to use, but defaults + * to a comma if the locale specific thousands separator isn't set. + */ +int commaize_number(char *buf, size_t len, int64_t number) +{ + char commabuf[22]; /* 64 bits == 20 digits, +1 for sign, +1 for NUL */ + const char *thousands_sep = ","; + unsigned int separator_len = 1; + struct lconv *localeinfo; + + int nchars, ndigits; + int chars_needed; + + int dest_offset; + int ii; + + if ((nchars = snprintf(commabuf, sizeof(commabuf), "%" PRId64, number)) + >= (int)sizeof(commabuf)) + { + errno = ENOMEM; + return -1; + } + + localeinfo = localeconv(); + if (localeinfo && localeinfo->thousands_sep && + localeinfo->thousands_sep[0]) + { + thousands_sep = localeinfo->thousands_sep; + separator_len = strlen(localeinfo->thousands_sep); + } + + ndigits = nchars; + if (commabuf[0] == '-') + ndigits--; + chars_needed = nchars + separator_len * ((ndigits - 1) / 3); + if (chars_needed + 1 > (int)len) + { + errno = ENOMEM; + return -1; + } + + buf[chars_needed] = '\0'; + + dest_offset = chars_needed - 1; + for (ii = 1 ; ii <= nchars ; ii++) + { + buf[dest_offset] = commabuf[nchars - ii]; + + if ((ii % 3) == 0 && ii < (int)nchars && commabuf[nchars - ii - 1] != '-') + { + memcpy(&buf[dest_offset - separator_len], thousands_sep, separator_len); + dest_offset -= separator_len; + } + + dest_offset--; + } + return chars_needed; +} +