xref: /illumos-gate/usr/src/lib/libc/port/gen/strtonum.c (revision 223750d9)
103100a63Svk /*
203100a63Svk  * Copyright (c) 2004 Ted Unangst and Todd Miller
303100a63Svk  * All rights reserved.
403100a63Svk  *
503100a63Svk  * Permission to use, copy, modify, and distribute this software for any
603100a63Svk  * purpose with or without fee is hereby granted, provided that the above
703100a63Svk  * copyright notice and this permission notice appear in all copies.
803100a63Svk  *
903100a63Svk  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1003100a63Svk  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1103100a63Svk  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1203100a63Svk  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1303100a63Svk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1403100a63Svk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1503100a63Svk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1603100a63Svk  */
1703100a63Svk 
18*223750d9SAndy Fiddaman /*
19*223750d9SAndy Fiddaman  * Copyright 2023 Oxide Computer Company
20*223750d9SAndy Fiddaman  */
21*223750d9SAndy Fiddaman 
2203100a63Svk #include <errno.h>
2303100a63Svk #include <limits.h>
2403100a63Svk #include <stdlib.h>
2503100a63Svk 
264585130bSYuri Pankov #define	INVALID		1
274585130bSYuri Pankov #define	TOOSMALL	2
284585130bSYuri Pankov #define	TOOLARGE	3
29*223750d9SAndy Fiddaman #define	BADBASE		4
30*223750d9SAndy Fiddaman 
31*223750d9SAndy Fiddaman #define	MBASE		('z' - 'a' + 1 + 10)
3203100a63Svk 
334585130bSYuri Pankov long long
strtonumx(const char * numstr,long long minval,long long maxval,const char ** errstrp,int base)34*223750d9SAndy Fiddaman strtonumx(const char *numstr, long long minval, long long maxval,
35*223750d9SAndy Fiddaman     const char **errstrp, int base)
3603100a63Svk {
3703100a63Svk 	long long ll = 0;
3803100a63Svk 	int error = 0;
394585130bSYuri Pankov 	char *ep;
4003100a63Svk 	struct errval {
4103100a63Svk 		const char *errstr;
4203100a63Svk 		int err;
43*223750d9SAndy Fiddaman 	} ev[5] = {
4403100a63Svk 		{ NULL,		0 },
4503100a63Svk 		{ "invalid",	EINVAL },
4603100a63Svk 		{ "too small",	ERANGE },
4703100a63Svk 		{ "too large",	ERANGE },
48*223750d9SAndy Fiddaman 		{ "unparsable; invalid base specified", EINVAL },
4903100a63Svk 	};
5003100a63Svk 
5103100a63Svk 	ev[0].err = errno;
5203100a63Svk 	errno = 0;
534585130bSYuri Pankov 	if (minval > maxval) {
5403100a63Svk 		error = INVALID;
55*223750d9SAndy Fiddaman 	} else if (base < 0 || base > MBASE || base == 1) {
56*223750d9SAndy Fiddaman 		error = BADBASE;
574585130bSYuri Pankov 	} else {
58*223750d9SAndy Fiddaman 		ll = strtoll(numstr, &ep, base);
5903100a63Svk 		if (numstr == ep || *ep != '\0')
6003100a63Svk 			error = INVALID;
6103100a63Svk 		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
6203100a63Svk 			error = TOOSMALL;
6303100a63Svk 		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
6403100a63Svk 			error = TOOLARGE;
6503100a63Svk 	}
6603100a63Svk 	if (errstrp != NULL)
6703100a63Svk 		*errstrp = ev[error].errstr;
6803100a63Svk 	errno = ev[error].err;
69*223750d9SAndy Fiddaman 	if (error != 0)
7003100a63Svk 		ll = 0;
7103100a63Svk 
724585130bSYuri Pankov 	return (ll);
7303100a63Svk }
74*223750d9SAndy Fiddaman 
75*223750d9SAndy Fiddaman long long
strtonum(const char * numstr,long long minval,long long maxval,const char ** errstrp)76*223750d9SAndy Fiddaman strtonum(const char *numstr, long long minval, long long maxval,
77*223750d9SAndy Fiddaman     const char **errstrp)
78*223750d9SAndy Fiddaman {
79*223750d9SAndy Fiddaman 	return (strtonumx(numstr, minval, maxval, errstrp, 10));
80*223750d9SAndy Fiddaman }
81