xref: /netbsd-src/external/bsd/ntp/dist/libntp/atouint.c (revision cdfa2a7ef92791ba9db70a584a1d904730e6fb46)
1*cdfa2a7eSchristos /*	$NetBSD: atouint.c,v 1.9 2020/05/25 20:47:24 christos Exp $	*/
2abb0f93cSkardel 
32950cc38Schristos #include <config.h>
4abb0f93cSkardel #include <sys/types.h>
5abb0f93cSkardel #include <ctype.h>
6abb0f93cSkardel 
7abb0f93cSkardel #include "ntp_types.h"
8abb0f93cSkardel #include "ntp_stdlib.h"
9abb0f93cSkardel 
102950cc38Schristos /*
112950cc38Schristos  * atouint() - convert an ascii string representing a whole base 10
122950cc38Schristos  *	       number to u_long *uval, returning TRUE if successful.
132950cc38Schristos  *	       Does not modify *uval and returns FALSE if str is not
142950cc38Schristos  *	       a positive base10 integer or is too large for a u_int32.
152950cc38Schristos  *	       this function uses u_long but should use u_int32, and
162950cc38Schristos  *	       probably be renamed.
172950cc38Schristos  */
18abb0f93cSkardel int
atouint(const char * str,u_long * uval)19abb0f93cSkardel atouint(
20abb0f93cSkardel 	const char *str,
21abb0f93cSkardel 	u_long *uval
22abb0f93cSkardel 	)
23abb0f93cSkardel {
242950cc38Schristos 	u_long u;
252950cc38Schristos 	const char *cp;
26abb0f93cSkardel 
27abb0f93cSkardel 	cp = str;
282950cc38Schristos 	if ('\0' == *cp)
29abb0f93cSkardel 		return 0;
30abb0f93cSkardel 
31abb0f93cSkardel 	u = 0;
322950cc38Schristos 	while ('\0' != *cp) {
33ed38567fSchristos 		if (!isdigit((unsigned char)*cp))
34abb0f93cSkardel 			return 0;
35abb0f93cSkardel 		if (u > 429496729 || (u == 429496729 && *cp >= '6'))
36abb0f93cSkardel 			return 0;		/* overflow */
372950cc38Schristos 		/* hand-optimized u *= 10; */
38abb0f93cSkardel 		u = (u << 3) + (u << 1);
392950cc38Schristos 		u += *cp++ - '0';		/* not '\0' */
40abb0f93cSkardel 	}
41abb0f93cSkardel 
42abb0f93cSkardel 	*uval = u;
43abb0f93cSkardel 	return 1;
44abb0f93cSkardel }
45