mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
Import of OpenBSD's strtonum(3) which is a nicer version of strtoll(3)
providing proper error checking and other improvements. Obtained from: OpenBSD Requested by: flz (to port Open[BGP|OSPF]D) MFC after: 3 days
This commit is contained in:
parent
39092e79ed
commit
c74dfa2faf
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=156707
|
@ -271,6 +271,8 @@ int sradixsort(const unsigned char **, int, const unsigned char *,
|
||||||
unsigned);
|
unsigned);
|
||||||
void sranddev(void);
|
void sranddev(void);
|
||||||
void srandomdev(void);
|
void srandomdev(void);
|
||||||
|
long long
|
||||||
|
strtonum(const char *, long long, long long, const char **);
|
||||||
|
|
||||||
/* Deprecated interfaces, to be removed in FreeBSD 6.0. */
|
/* Deprecated interfaces, to be removed in FreeBSD 6.0. */
|
||||||
__int64_t
|
__int64_t
|
||||||
|
|
|
@ -10,8 +10,8 @@ MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
|
||||||
insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c \
|
insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c \
|
||||||
merge.c putenv.c qsort.c qsort_r.c radixsort.c rand.c random.c \
|
merge.c putenv.c qsort.c qsort_r.c radixsort.c rand.c random.c \
|
||||||
reallocf.c realpath.c remque.c setenv.c strfmon.c strtoimax.c \
|
reallocf.c realpath.c remque.c setenv.c strfmon.c strtoimax.c \
|
||||||
strtol.c strtoll.c strtoq.c strtoul.c strtoull.c strtoumax.c strtouq.c \
|
strtol.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c strtoumax.c \
|
||||||
system.c tdelete.c tfind.c tsearch.c twalk.c
|
strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
|
||||||
|
|
||||||
SYM_MAPS+= ${.CURDIR}/stdlib/Symbol.map
|
SYM_MAPS+= ${.CURDIR}/stdlib/Symbol.map
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \
|
||||||
hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \
|
hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \
|
||||||
lsearch.3 malloc.3 memory.3 posix_memalign.3 qsort.3 radixsort.3 \
|
lsearch.3 malloc.3 memory.3 posix_memalign.3 qsort.3 radixsort.3 \
|
||||||
rand.3 random.3 \
|
rand.3 random.3 \
|
||||||
realpath.3 strfmon.3 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3
|
realpath.3 strfmon.3 strtod.3 strtol.3 strtonum.3 strtoul.3 system.3 \
|
||||||
|
tsearch.3
|
||||||
|
|
||||||
MLINKS+=a64l.3 l64a.3 a64l.3 l64a_r.3
|
MLINKS+=a64l.3 l64a.3 a64l.3 l64a_r.3
|
||||||
MLINKS+=atol.3 atoll.3
|
MLINKS+=atol.3 atoll.3
|
||||||
|
|
|
@ -77,6 +77,7 @@ FBSD_1.0 {
|
||||||
strtoimax;
|
strtoimax;
|
||||||
strtol;
|
strtol;
|
||||||
strtoll;
|
strtoll;
|
||||||
|
strtonum;
|
||||||
strtoq;
|
strtoq;
|
||||||
strtoul;
|
strtoul;
|
||||||
strtoull;
|
strtoull;
|
||||||
|
|
154
lib/libc/stdlib/strtonum.3
Normal file
154
lib/libc/stdlib/strtonum.3
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
.\" Copyright (c) 2004 Ted Unangst
|
||||||
|
.\"
|
||||||
|
.\" Permission to use, copy, modify, and distribute this software for any
|
||||||
|
.\" purpose with or without fee is hereby granted, provided that the above
|
||||||
|
.\" copyright notice and this permission notice appear in all copies.
|
||||||
|
.\"
|
||||||
|
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
.\"
|
||||||
|
.\" $OpenBSD: strtonum.3,v 1.12 2005/10/26 11:37:58 jmc Exp $
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd April 29, 2004
|
||||||
|
.Dt STRTONUM 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm strtonum
|
||||||
|
.Nd "reliably convert string value to an integer"
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Fd #include <stdlib.h>
|
||||||
|
.Fd #include <limits.h>
|
||||||
|
.Ft long long
|
||||||
|
.Fo strtonum
|
||||||
|
.Fa "const char *nptr"
|
||||||
|
.Fa "long long minval"
|
||||||
|
.Fa "long long maxval"
|
||||||
|
.Fa "const char **errstr"
|
||||||
|
.Fc
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn strtonum
|
||||||
|
function converts the string in
|
||||||
|
.Fa nptr
|
||||||
|
to a
|
||||||
|
.Li long long
|
||||||
|
value.
|
||||||
|
The
|
||||||
|
.Fn strtonum
|
||||||
|
function was designed to facilitate safe, robust programming
|
||||||
|
and overcome the shortcomings of the
|
||||||
|
.Xr atoi 3
|
||||||
|
and
|
||||||
|
.Xr strtol 3
|
||||||
|
family of interfaces.
|
||||||
|
.Pp
|
||||||
|
The string may begin with an arbitrary amount of whitespace
|
||||||
|
(as determined by
|
||||||
|
.Xr isspace 3 )
|
||||||
|
followed by a single optional
|
||||||
|
.Ql +
|
||||||
|
or
|
||||||
|
.Ql -
|
||||||
|
sign.
|
||||||
|
.Pp
|
||||||
|
The remainder of the string is converted to a
|
||||||
|
.Li long long
|
||||||
|
value according to base 10.
|
||||||
|
.Pp
|
||||||
|
The value obtained is then checked against the provided
|
||||||
|
.Fa minval
|
||||||
|
and
|
||||||
|
.Fa maxval
|
||||||
|
bounds.
|
||||||
|
If
|
||||||
|
.Fa errstr
|
||||||
|
is non-null,
|
||||||
|
.Fn strtonum
|
||||||
|
stores an error string in
|
||||||
|
.Fa *errstr
|
||||||
|
indicating the failure.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn strtonum
|
||||||
|
function returns the result of the conversion,
|
||||||
|
unless the value would exceed the provided bounds or is invalid.
|
||||||
|
On error, 0 is returned,
|
||||||
|
.Va errno
|
||||||
|
is set, and
|
||||||
|
.Fa errstr
|
||||||
|
will point to an error message.
|
||||||
|
.Fa *errstr
|
||||||
|
will be set to
|
||||||
|
.Dv NULL
|
||||||
|
on success;
|
||||||
|
this fact can be used to differentiate
|
||||||
|
a successful return of 0 from an error.
|
||||||
|
.Sh EXAMPLES
|
||||||
|
Using
|
||||||
|
.Fn strtonum
|
||||||
|
correctly is meant to be simpler than the alternative functions.
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
int iterations;
|
||||||
|
const char *errstr;
|
||||||
|
|
||||||
|
iterations = strtonum(optarg, 1, 64, &errstr);
|
||||||
|
if (errstr)
|
||||||
|
errx(1, "number of iterations is %s: %s", errstr, optarg);
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The above example will guarantee that the value of iterations is between
|
||||||
|
1 and 64 (inclusive).
|
||||||
|
.Sh ERRORS
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er ERANGE
|
||||||
|
The given string was out of range.
|
||||||
|
.It Bq Er EINVAL
|
||||||
|
The given string did not consist solely of digit characters.
|
||||||
|
.It Bq Er EINVAL
|
||||||
|
.Ar minval
|
||||||
|
was larger than
|
||||||
|
.Ar maxval .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
If an error occurs,
|
||||||
|
.Fa errstr
|
||||||
|
will be set to one of the following strings:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width "too largeXX" -compact
|
||||||
|
.It too large
|
||||||
|
The result was larger than the provided maximum value.
|
||||||
|
.It too small
|
||||||
|
The result was smaller than the provided minimum value.
|
||||||
|
.It invalid
|
||||||
|
The string did not consist solely of digit characters.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr atof 3 ,
|
||||||
|
.Xr atoi 3 ,
|
||||||
|
.Xr atol 3 ,
|
||||||
|
.Xr atoll 3 ,
|
||||||
|
.Xr sscanf 3 ,
|
||||||
|
.Xr strtod 3 ,
|
||||||
|
.Xr strtol 3 ,
|
||||||
|
.Xr strtoul 3
|
||||||
|
.Sh STANDARDS
|
||||||
|
.Fn strtonum
|
||||||
|
is an
|
||||||
|
.Ox
|
||||||
|
extension.
|
||||||
|
The existing alternatives, such as
|
||||||
|
.Xr atoi 3
|
||||||
|
and
|
||||||
|
.Xr strtol 3 ,
|
||||||
|
are either impossible or difficult to use safely.
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn strtonum
|
||||||
|
function first appeared in
|
||||||
|
.Ox 3.6 .
|
68
lib/libc/stdlib/strtonum.c
Normal file
68
lib/libc/stdlib/strtonum.c
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2004 Ted Unangst and Todd Miller
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define INVALID 1
|
||||||
|
#define TOOSMALL 2
|
||||||
|
#define TOOLARGE 3
|
||||||
|
|
||||||
|
long long
|
||||||
|
strtonum(const char *numstr, long long minval, long long maxval,
|
||||||
|
const char **errstrp)
|
||||||
|
{
|
||||||
|
long long ll = 0;
|
||||||
|
char *ep;
|
||||||
|
int error = 0;
|
||||||
|
struct errval {
|
||||||
|
const char *errstr;
|
||||||
|
int err;
|
||||||
|
} ev[4] = {
|
||||||
|
{ NULL, 0 },
|
||||||
|
{ "invalid", EINVAL },
|
||||||
|
{ "too small", ERANGE },
|
||||||
|
{ "too large", ERANGE },
|
||||||
|
};
|
||||||
|
|
||||||
|
ev[0].err = errno;
|
||||||
|
errno = 0;
|
||||||
|
if (minval > maxval)
|
||||||
|
error = INVALID;
|
||||||
|
else {
|
||||||
|
ll = strtoll(numstr, &ep, 10);
|
||||||
|
if (numstr == ep || *ep != '\0')
|
||||||
|
error = INVALID;
|
||||||
|
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
|
||||||
|
error = TOOSMALL;
|
||||||
|
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
|
||||||
|
error = TOOLARGE;
|
||||||
|
}
|
||||||
|
if (errstrp != NULL)
|
||||||
|
*errstrp = ev[error].errstr;
|
||||||
|
errno = ev[error].err;
|
||||||
|
if (error)
|
||||||
|
ll = 0;
|
||||||
|
|
||||||
|
return (ll);
|
||||||
|
}
|
Loading…
Reference in a new issue