strtoull.c revision 87023
1198090Srdivacky/*-
2198090Srdivacky * Copyright (c) 1992, 1993
3198090Srdivacky *	The Regents of the University of California.  All rights reserved.
4198090Srdivacky *
5198090Srdivacky * Redistribution and use in source and binary forms, with or without
6198090Srdivacky * modification, are permitted provided that the following conditions
7198090Srdivacky * are met:
8198090Srdivacky * 1. Redistributions of source code must retain the above copyright
9198090Srdivacky *    notice, this list of conditions and the following disclaimer.
10198090Srdivacky * 2. Redistributions in binary form must reproduce the above copyright
11198090Srdivacky *    notice, this list of conditions and the following disclaimer in the
12198090Srdivacky *    documentation and/or other materials provided with the distribution.
13198090Srdivacky * 3. All advertising materials mentioning features or use of this software
14198090Srdivacky *    must display the following acknowledgement:
15198090Srdivacky *	This product includes software developed by the University of
16198090Srdivacky *	California, Berkeley and its contributors.
17198090Srdivacky * 4. Neither the name of the University nor the names of its contributors
18198090Srdivacky *    may be used to endorse or promote products derived from this software
19198090Srdivacky *    without specific prior written permission.
20198090Srdivacky *
21198090Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22198090Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23198090Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24198090Srdivacky * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25198090Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26198090Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27198090Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28198090Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29198090Srdivacky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30198090Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31198090Srdivacky * SUCH DAMAGE.
32198090Srdivacky *
33198090Srdivacky * $FreeBSD: head/lib/libc/stdlib/strtoull.c 87023 2001-11-28 02:35:35Z fenner $
34198090Srdivacky */
35198090Srdivacky
36198090Srdivacky#if defined(LIBC_SCCS) && !defined(lint)
37198090Srdivackystatic char sccsid[] = "@(#)strtouq.c	8.1 (Berkeley) 6/4/93";
38198090Srdivacky#endif /* LIBC_SCCS and not lint */
39198090Srdivacky
40198090Srdivacky#include <limits.h>
41198090Srdivacky#include <errno.h>
42198090Srdivacky#include <ctype.h>
43198090Srdivacky#include <stdlib.h>
44198090Srdivacky
45198090Srdivacky/*
46198090Srdivacky * Convert a string to an unsigned long long integer.
47198090Srdivacky *
48198090Srdivacky * Assumes that the upper and lower case
49198090Srdivacky * alphabets and digits are each contiguous.
50198090Srdivacky */
51198090Srdivackyunsigned long long
52198090Srdivackystrtoull(nptr, endptr, base)
53198090Srdivacky	const char *nptr;
54198090Srdivacky	char **endptr;
55198090Srdivacky	int base;
56198090Srdivacky{
57198090Srdivacky	const char *s;
58198090Srdivacky	unsigned long long acc;
59198090Srdivacky	unsigned char c;
60198090Srdivacky	unsigned long long cutoff;
61198090Srdivacky	int neg, any, cutlim;
62198090Srdivacky
63198090Srdivacky	/*
64198090Srdivacky	 * See strtoq for comments as to the logic used.
65198090Srdivacky	 */
66198090Srdivacky	s = nptr;
67198090Srdivacky	do {
68198090Srdivacky		c = *s++;
69198090Srdivacky	} while (isspace(c));
70198090Srdivacky	if (c == '-') {
71198090Srdivacky		neg = 1;
72198090Srdivacky		c = *s++;
73198090Srdivacky	} else {
74198090Srdivacky		neg = 0;
75198090Srdivacky		if (c == '+')
76198090Srdivacky			c = *s++;
77198090Srdivacky	}
78198090Srdivacky	if ((base == 0 || base == 16) &&
79198090Srdivacky	    c == '0' && (*s == 'x' || *s == 'X')) {
80198090Srdivacky		c = s[1];
81198090Srdivacky		s += 2;
82198090Srdivacky		base = 16;
83198090Srdivacky	}
84198090Srdivacky	if (base == 0)
85198090Srdivacky		base = c == '0' ? 8 : 10;
86198090Srdivacky	acc = any = 0;
87198090Srdivacky	if (base < 2 || base > 36)
88198090Srdivacky		goto noconv;
89198090Srdivacky
90198090Srdivacky	cutoff = ULLONG_MAX / base;
91198090Srdivacky	cutlim = ULLONG_MAX % base;
92198090Srdivacky	for ( ; ; c = *s++) {
93198090Srdivacky		if (isxdigit(c))
94198090Srdivacky			c = digittoint(c);
95198090Srdivacky		else if (isascii(c) && isalpha(c))
96198090Srdivacky			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
97198090Srdivacky		else
98198090Srdivacky			break;
99198090Srdivacky		if (c >= base)
100198090Srdivacky			break;
101198090Srdivacky		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
102198090Srdivacky			any = -1;
103198090Srdivacky		else {
104198090Srdivacky			any = 1;
105198090Srdivacky			acc *= base;
106198090Srdivacky			acc += c;
107198090Srdivacky		}
108198090Srdivacky	}
109198090Srdivacky	if (any < 0) {
110198090Srdivacky		acc = ULLONG_MAX;
111198090Srdivacky		errno = ERANGE;
112198090Srdivacky	} else if (!any) {
113198090Srdivackynoconv:
114198090Srdivacky		errno = EINVAL;
115198090Srdivacky	} else if (neg)
116198090Srdivacky		acc = -acc;
117198090Srdivacky	if (endptr != NULL)
118198090Srdivacky		*endptr = (char *)(any ? s - 1 : nptr);
119198090Srdivacky	return (acc);
120198090Srdivacky}
121198090Srdivacky