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
aaa33da2ed
commit
9ec6603878
@ -271,6 +271,8 @@ int sradixsort(const unsigned char **, int, const unsigned char *,
|
||||
unsigned);
|
||||
void sranddev(void);
|
||||
void srandomdev(void);
|
||||
long long
|
||||
strtonum(const char *, long long, long long, const char **);
|
||||
|
||||
/* Deprecated interfaces, to be removed in FreeBSD 6.0. */
|
||||
__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 \
|
||||
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 \
|
||||
strtol.c strtoll.c strtoq.c strtoul.c strtoull.c strtoumax.c strtouq.c \
|
||||
system.c tdelete.c tfind.c tsearch.c twalk.c
|
||||
strtol.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c strtoumax.c \
|
||||
strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
|
||||
|
||||
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 \
|
||||
lsearch.3 malloc.3 memory.3 posix_memalign.3 qsort.3 radixsort.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+=atol.3 atoll.3
|
||||
|
@ -77,6 +77,7 @@ FBSD_1.0 {
|
||||
strtoimax;
|
||||
strtol;
|
||||
strtoll;
|
||||
strtonum;
|
||||
strtoq;
|
||||
strtoul;
|
||||
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 New Issue
Block a user