xref: /rk3399_ARM-atf/lib/libc/strtoull.c (revision d56b957c2104f624994d5f20fdaa989079c06a6f)
1*d56b957cSMadhukar Pappireddy /*-
2*d56b957cSMadhukar Pappireddy  * SPDX-License-Identifier: BSD-3-Clause
3*d56b957cSMadhukar Pappireddy  *
4*d56b957cSMadhukar Pappireddy  * Copyright (c) 1992, 1993
5*d56b957cSMadhukar Pappireddy  *	The Regents of the University of California.  All rights reserved.
6*d56b957cSMadhukar Pappireddy  *
7*d56b957cSMadhukar Pappireddy  * Copyright (c) 2011 The FreeBSD Foundation
8*d56b957cSMadhukar Pappireddy  * All rights reserved.
9*d56b957cSMadhukar Pappireddy  * Portions of this software were developed by David Chisnall
10*d56b957cSMadhukar Pappireddy  * under sponsorship from the FreeBSD Foundation.
11*d56b957cSMadhukar Pappireddy  *
12*d56b957cSMadhukar Pappireddy  * Redistribution and use in source and binary forms, with or without
13*d56b957cSMadhukar Pappireddy  * modification, are permitted provided that the following conditions
14*d56b957cSMadhukar Pappireddy  * are met:
15*d56b957cSMadhukar Pappireddy  * 1. Redistributions of source code must retain the above copyright
16*d56b957cSMadhukar Pappireddy  *    notice, this list of conditions and the following disclaimer.
17*d56b957cSMadhukar Pappireddy  * 2. Redistributions in binary form must reproduce the above copyright
18*d56b957cSMadhukar Pappireddy  *    notice, this list of conditions and the following disclaimer in the
19*d56b957cSMadhukar Pappireddy  *    documentation and/or other materials provided with the distribution.
20*d56b957cSMadhukar Pappireddy  * 3. Neither the name of the University nor the names of its contributors
21*d56b957cSMadhukar Pappireddy  *    may be used to endorse or promote products derived from this software
22*d56b957cSMadhukar Pappireddy  *    without specific prior written permission.
23*d56b957cSMadhukar Pappireddy  *
24*d56b957cSMadhukar Pappireddy  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25*d56b957cSMadhukar Pappireddy  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*d56b957cSMadhukar Pappireddy  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27*d56b957cSMadhukar Pappireddy  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28*d56b957cSMadhukar Pappireddy  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29*d56b957cSMadhukar Pappireddy  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30*d56b957cSMadhukar Pappireddy  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31*d56b957cSMadhukar Pappireddy  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32*d56b957cSMadhukar Pappireddy  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33*d56b957cSMadhukar Pappireddy  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34*d56b957cSMadhukar Pappireddy  * SUCH DAMAGE.
35*d56b957cSMadhukar Pappireddy  */
36*d56b957cSMadhukar Pappireddy 
37*d56b957cSMadhukar Pappireddy #include <errno.h>
38*d56b957cSMadhukar Pappireddy #include <limits.h>
39*d56b957cSMadhukar Pappireddy #include <stddef.h>
40*d56b957cSMadhukar Pappireddy #include <stdlib.h>
41*d56b957cSMadhukar Pappireddy 
42*d56b957cSMadhukar Pappireddy /*
43*d56b957cSMadhukar Pappireddy  * Convert a string to an unsigned long long integer.
44*d56b957cSMadhukar Pappireddy  *
45*d56b957cSMadhukar Pappireddy  * Assumes that the upper and lower case
46*d56b957cSMadhukar Pappireddy  * alphabets and digits are each contiguous.
47*d56b957cSMadhukar Pappireddy  */
48*d56b957cSMadhukar Pappireddy unsigned long long strtoull(const char *nptr, char **endptr, int base)
49*d56b957cSMadhukar Pappireddy {
50*d56b957cSMadhukar Pappireddy 	const char *s;
51*d56b957cSMadhukar Pappireddy 	unsigned long long acc;
52*d56b957cSMadhukar Pappireddy 	char c;
53*d56b957cSMadhukar Pappireddy 	unsigned long long cutoff;
54*d56b957cSMadhukar Pappireddy 	int neg, any, cutlim;
55*d56b957cSMadhukar Pappireddy 
56*d56b957cSMadhukar Pappireddy 	/*
57*d56b957cSMadhukar Pappireddy 	 * See strtoq for comments as to the logic used.
58*d56b957cSMadhukar Pappireddy 	 */
59*d56b957cSMadhukar Pappireddy 	s = nptr;
60*d56b957cSMadhukar Pappireddy 	do {
61*d56b957cSMadhukar Pappireddy 		c = *s++;
62*d56b957cSMadhukar Pappireddy 	} while (isspace((unsigned char)c));
63*d56b957cSMadhukar Pappireddy 	if (c == '-') {
64*d56b957cSMadhukar Pappireddy 		neg = 1;
65*d56b957cSMadhukar Pappireddy 		c = *s++;
66*d56b957cSMadhukar Pappireddy 	} else {
67*d56b957cSMadhukar Pappireddy 		neg = 0;
68*d56b957cSMadhukar Pappireddy 		if (c == '+')
69*d56b957cSMadhukar Pappireddy 			c = *s++;
70*d56b957cSMadhukar Pappireddy 	}
71*d56b957cSMadhukar Pappireddy 	if ((base == 0 || base == 16) &&
72*d56b957cSMadhukar Pappireddy 	    c == '0' && (*s == 'x' || *s == 'X') &&
73*d56b957cSMadhukar Pappireddy 	    ((s[1] >= '0' && s[1] <= '9') ||
74*d56b957cSMadhukar Pappireddy 	    (s[1] >= 'A' && s[1] <= 'F') ||
75*d56b957cSMadhukar Pappireddy 	    (s[1] >= 'a' && s[1] <= 'f'))) {
76*d56b957cSMadhukar Pappireddy 		c = s[1];
77*d56b957cSMadhukar Pappireddy 		s += 2;
78*d56b957cSMadhukar Pappireddy 		base = 16;
79*d56b957cSMadhukar Pappireddy 	}
80*d56b957cSMadhukar Pappireddy 	if (base == 0)
81*d56b957cSMadhukar Pappireddy 		base = c == '0' ? 8 : 10;
82*d56b957cSMadhukar Pappireddy 	acc = any = 0;
83*d56b957cSMadhukar Pappireddy 
84*d56b957cSMadhukar Pappireddy 	cutoff = ULLONG_MAX / base;
85*d56b957cSMadhukar Pappireddy 	cutlim = ULLONG_MAX % base;
86*d56b957cSMadhukar Pappireddy 	for ( ; ; c = *s++) {
87*d56b957cSMadhukar Pappireddy 		if (c >= '0' && c <= '9')
88*d56b957cSMadhukar Pappireddy 			c -= '0';
89*d56b957cSMadhukar Pappireddy 		else if (c >= 'A' && c <= 'Z')
90*d56b957cSMadhukar Pappireddy 			c -= 'A' - 10;
91*d56b957cSMadhukar Pappireddy 		else if (c >= 'a' && c <= 'z')
92*d56b957cSMadhukar Pappireddy 			c -= 'a' - 10;
93*d56b957cSMadhukar Pappireddy 		else
94*d56b957cSMadhukar Pappireddy 			break;
95*d56b957cSMadhukar Pappireddy 		if (c >= base)
96*d56b957cSMadhukar Pappireddy 			break;
97*d56b957cSMadhukar Pappireddy 		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
98*d56b957cSMadhukar Pappireddy 			any = -1;
99*d56b957cSMadhukar Pappireddy 		else {
100*d56b957cSMadhukar Pappireddy 			any = 1;
101*d56b957cSMadhukar Pappireddy 			acc *= base;
102*d56b957cSMadhukar Pappireddy 			acc += c;
103*d56b957cSMadhukar Pappireddy 		}
104*d56b957cSMadhukar Pappireddy 	}
105*d56b957cSMadhukar Pappireddy 	if (any < 0) {
106*d56b957cSMadhukar Pappireddy 		acc = ULLONG_MAX;
107*d56b957cSMadhukar Pappireddy 	} else if (neg)
108*d56b957cSMadhukar Pappireddy 		acc = -acc;
109*d56b957cSMadhukar Pappireddy 	if (endptr != NULL)
110*d56b957cSMadhukar Pappireddy 		*endptr = (char *)(any ? s - 1 : nptr);
111*d56b957cSMadhukar Pappireddy 	return (acc);
112*d56b957cSMadhukar Pappireddy }
113