xref: /dragonfly/lib/libc/stdlib/strtonum.c (revision 1bf4b486)
1 /* $OpenBSD: strtonum.c,v 1.5 2004/07/16 18:36:05 otto Exp $ */
2 /* $DragonFly: src/lib/libc/stdlib/strtonum.c,v 1.1 2004/08/15 16:01:11 joerg Exp $ */
3 /*
4  * Copyright (c) 2004 Ted Unangst and Todd Miller
5  * All rights reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <errno.h>
21 #include <limits.h>
22 #include <stdlib.h>
23 
24 #define INVALID 	1
25 #define TOOSMALL 	2
26 #define TOOLARGE 	3
27 
28 static struct errval {
29 	const char *errstr;
30 	int err;
31 } ev[4] = {
32 	{ NULL,		0 },
33 	{ "invalid",	EINVAL },
34 	{ "too small",	ERANGE },
35 	{ "too large",	ERANGE },
36 };
37 
38 unsigned long long
39 strtonum(const char *numstr, long long minval, unsigned long long umaxval,
40 	 const char **errstrp)
41 {
42 	long long ll, maxval = (long long)umaxval;
43 	unsigned long long ull = 0;
44 	char *ep;
45 	int error = 0;
46 
47 	ev[0].err = errno;
48 	errno = 0;
49 	if (umaxval > LLONG_MAX ) {
50 		if (minval < 0) {
51 			error = INVALID;
52 			goto done;
53 		}
54 		ull = strtoull(numstr, &ep, 10);
55 		if (numstr == ep || *ep != '\0')
56 			error = INVALID;
57 		else if ((ull == ULLONG_MAX && errno == ERANGE) ||
58 			 ull > umaxval)
59 			error = TOOLARGE;
60 		else if (ull < minval)
61 			error = TOOSMALL;
62 	} else {
63 		if (minval > maxval || maxval < minval) {
64 			error = INVALID;
65 			goto done;
66 		}
67 		ll = strtoll(numstr, &ep, 10);
68 		if (numstr == ep || *ep != '\0')
69 			error = INVALID;
70 		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
71 			error = TOOSMALL;
72 		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
73 			error = TOOLARGE;
74 		ull = (unsigned long long)ll;
75 	}
76 done:
77 	if (errstrp != NULL)
78 		*errstrp = ev[error].errstr;
79 	errno = ev[error].err;
80 	if (error)
81 		ull = 0;
82 
83 	return(ull);
84 }
85