add strsuftoll(3) and strsuftollx(3) - parse a string for a number

with an optional suffix, product (two numbers separated by `x'), and
provide range checking
This commit is contained in:
lukem 2002-11-29 12:58:14 +00:00
parent a9a3da8aca
commit 6ca5b5bb68
6 changed files with 389 additions and 8 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: stdlib.h,v 1.56 2002/05/24 04:01:43 itojun Exp $ */
/* $NetBSD: stdlib.h,v 1.57 2002/11/29 12:58:14 lukem Exp $ */
/*-
* Copyright (c) 1990, 1993
@ -270,6 +270,12 @@ quad_t qabs __P((quad_t));
quad_t strtoq __P((const char * __restrict, char ** __restrict, int));
u_quad_t strtouq __P((const char * __restrict, char ** __restrict, int));
/* LONGLONG */
long long strsuftoll(const char *, const char *, long long, long long);
/* LONGLONG */
long long strsuftollx(const char *, const char *, long long, long long,
char *, size_t);
int l64a_r __P((long, char *, int));
size_t shquote __P((const char *arg, char *buf, size_t bufsize));

View File

@ -1,4 +1,4 @@
/* $NetBSD: namespace.h,v 1.72 2002/11/08 00:13:29 fvdl Exp $ */
/* $NetBSD: namespace.h,v 1.73 2002/11/29 12:58:16 lukem Exp $ */
/*-
* Copyright (c) 1997-2002 The NetBSD Foundation, Inc.
@ -436,6 +436,8 @@
#define strptime _strptime
#define strsep _strsep
#define strsignal _strsignal
#define strsuftoll _strsuftoll
#define strsuftollx _strsuftollx
#define strsvis _strsvis
#define strsvisx _strsvisx
#define strtok_r _strtok_r

View File

@ -1,4 +1,4 @@
# $NetBSD: shlib_version,v 1.122 2002/11/08 00:13:51 fvdl Exp $
# $NetBSD: shlib_version,v 1.123 2002/11/29 12:58:16 lukem Exp $
# Remember to update distrib/sets/lists/base/shl.* when changing
#
# things we wish to do on next major version bump:
@ -11,4 +11,4 @@
# - libc/net/getaddrinfo.c, netdb.h: remove __ai_pad0
#
major=12
minor=89
minor=90

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile.inc,v 1.52 2001/04/28 15:41:30 kleink Exp $
# $NetBSD: Makefile.inc,v 1.53 2002/11/29 12:58:17 lukem Exp $
# from: @(#)Makefile.inc 8.3 (Berkeley) 2/4/95
# stdlib sources
@ -11,7 +11,8 @@ SRCS+= _rand48.c _strtoimax.c _strtoumax.c _strtoll.c _strtoull.c \
hcreate.c heapsort.c jrand48.c \
l64a.c lldiv.c lcong48.c lrand48.c malloc.c merge.c mrand48.c \
nrand48.c putenv.c qabs.c qdiv.c qsort.c radixsort.c \
rand.c rand_r.c random.c seed48.c setenv.c srand48.c strtod.c \
rand.c rand_r.c random.c seed48.c setenv.c srand48.c \
strsuftoll.c strtod.c \
strtoimax.c strtol.c strtoll.c strtoq.c strtoul.c strtoull.c \
strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
@ -24,8 +25,8 @@ SRCS+= _rand48.c _strtoimax.c _strtoumax.c _strtoll.c _strtoull.c \
MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
bsearch.3 div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 \
hcreate.3 labs.3 ldiv.3 llabs.3 lldiv.3 malloc.3 memory.3 qabs.3 \
qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 strtod.3 \
strtol.3 strtoul.3 system.3 tsearch.3
qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 \
strsuftoll.3 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3
MLINKS+=a64l.3 l64a.3
MLINKS+=a64l.3 l64a_r.3
@ -40,6 +41,7 @@ MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3
MLINKS+=radixsort.3 sradixsort.3
MLINKS+=strsuftoll.3 strsuftollx.3
MLINKS+=strtol.3 strtoimax.3
MLINKS+=strtol.3 strtoll.3
MLINKS+=strtol.3 strtoq.3

View File

@ -0,0 +1,117 @@
.\" $NetBSD: strsuftoll.3,v 1.1 2002/11/29 12:58:17 lukem Exp $
.\"
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Luke Mewburn.
.\"
.\" 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.
.\"
.Dd November 29, 2002
.Dt STRSUFTOLL 3
.Os
.Sh NAME
.Nm strsuftoll ,
.Nm strsuftollx
.Nd "convert a string to an long long, with suffix parsing"
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.Fd #include \*[Lt]stdlib.h\*[Gt]
.Ft long long
.Fn strsuftoll "const char *desc" "const char *val" "long long min" "long long max"
.Ft long long
.Fn strsuftollx "const char *desc" "const char *val" "long long min" "long long max" "char *errbuf" "size_t errbuflen"
.Sh DESCRIPTION
The functions
.Fn strsuftoll
and
.Fn strsuftollx
convert
.Fa val
into a long long number,
checking that the result is not smaller than
.Fa min
or larger than
.Fa max .
Two or more numbers may be separated by an
.Dq x
to indicate a product.
Each number may have one of the following optional suffices:
.Bl -tag -width 3n -offset indent -compact
.It b
Block; multiply by 512
.It k
Kilo; multiply by 1024 (1 KB)
.It m
Mega; multiply by 1048576 (1 MB)
.It g
Giga; multiply by 1073741824 (1 GB)
.It t
Tera; multiply by 1099511627776 (1 TB)
.It w
Word; multiply by the number of bytes in an integer
.El
.Pp
In the case of an error (range overflow or an invalid number),
.Fn strsuftollx
places a error message into
.Fa errbuf
(which is
.Fa errbuflen
bytes long) and returns 0,
and
.Fn strsuftoll
displays that error and terminates the process.
.Sh RETURN VALUES
The functions
.Fn strsuftoll
and
.Fn strsuftollx
return either the result of the conversion,
unless the value overflows or is not a number;
in the latter case,
.Fn strsuftoll
displays an error message and terminates the process with exit code 1,
and
.Fn strsuftollx
returns with 0 and
.Fa errbuf
contains a non-empty error message.
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er ERANGE
The given string was out of range; the value converted has been clamped.
.El
.Sh SEE ALSO
.Xr errx 3 ,
.Xr strtoll 3
.Sh BUGS
Ignores the current locale.

View File

@ -0,0 +1,254 @@
/* $NetBSD: strsuftoll.c,v 1.1 2002/11/29 12:58:17 lukem Exp $ */
/*-
* Copyright (c) 2001-2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn.
*
* 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.
*/
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* 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 University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: strsuftoll.c,v 1.1 2002/11/29 12:58:17 lukem Exp $");
#endif /* LIBC_SCCS and not lint */
#ifdef _LIBC
#include "namespace.h"
#endif
#if HAVE_CONFIG_H
#include "config.h"
#endif
#if !HAVE_STRSUFTOLL
#include <sys/types.h>
#include <sys/time.h>
#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _LIBC
# define _STRSUFTOLL _strsuftoll
# define _STRSUFTOLLX _strsuftollx
# ifdef __weak_alias
__weak_alias(strsuftoll, _strsuftoll)
__weak_alias(strsuftollx, _strsuftollx)
# endif
#else /* !LIBC */
# define _STRSUFTOLL strsuftoll
# define _STRSUFTOLLX strsuftollx
#endif /* !LIBC */
/*
* Convert an expression of the following forms to a (u)int64_t.
* 1) A positive decimal number.
* 2) A positive decimal number followed by a b (mult by 512).
* 3) A positive decimal number followed by a k (mult by 1024).
* 4) A positive decimal number followed by a m (mult by 1048576).
* 5) A positive decimal number followed by a w (mult by sizeof int)
* 6) Two or more positive decimal numbers (with/without k,b or w).
* separated by x (also * for backwards compatibility), specifying
* the product of the indicated values.
* Returns the result upon successful conversion, or exits with an
* appropriate error.
*
*/
/* LONGLONG */
long long
_STRSUFTOLL(const char *desc, const char *val,
long long min, long long max)
{
long long result;
char errbuf[100];
result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf));
if (*errbuf != '\0')
errx(1, "%s", errbuf);
return (result);
}
/*
* As strsuftoll(), but returns the error message into the provided buffer
* rather than exiting with it.
*/
/* LONGLONG */
long long
_STRSUFTOLLX(const char *desc, const char *val,
long long min, long long max, char *ebuf, size_t ebuflen)
{
long long num, t;
char *expr;
_DIAGASSERT(desc != NULL);
_DIAGASSERT(val != NULL);
_DIAGASSERT(ebuf != NULL);
errno = 0;
ebuf[0] = '\0';
while (isspace((unsigned char)*val)) /* Skip leading space */
val++;
num = strtoll(val, &expr, 0);
if (errno == ERANGE)
goto erange; /* Overflow */
if (expr == val) /* No digits */
goto badnum;
switch (*expr) {
case 'b':
t = num;
num *= 512; /* 1 block */
if (t > num)
goto erange;
++expr;
break;
case 'k':
t = num;
num *= 1024; /* 1 kilobyte */
if (t > num)
goto erange;
++expr;
break;
case 'm':
t = num;
num *= 1048576; /* 1 megabyte */
if (t > num)
goto erange;
++expr;
break;
case 'g':
t = num;
num *= 1073741824; /* 1 gigabyte */
if (t > num)
goto erange;
++expr;
break;
case 't':
t = num;
num *= 1099511627776LL; /* 1 terabyte */
if (t > num)
goto erange;
++expr;
break;
case 'w':
t = num;
num *= sizeof(int); /* 1 word */
if (t > num)
goto erange;
++expr;
break;
}
switch (*expr) {
case '\0':
break;
case '*': /* Backward compatible */
case 'x':
t = num;
num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen);
if (*ebuf != '\0')
return (0);
if (t > num) {
erange:
snprintf(ebuf, ebuflen,
"%s: %s", desc, strerror(ERANGE));
return (0);
}
break;
default:
badnum: snprintf(ebuf, ebuflen,
"%s `%s': illegal number", desc, val);
return (0);
}
if (num < min) {
/* LONGLONG */
snprintf(ebuf, ebuflen, "%s %lld is less than %lld.",
desc, (long long)num, (long long)min);
return (0);
}
if (num > max) {
/* LONGLONG */
snprintf(ebuf, ebuflen,
"%s %lld is greater than %lld.",
desc, (long long)num, (long long)min);
return (0);
}
*ebuf = '\0';
return (num);
}
#endif /* !HAVE_STRSUFTOLL */