xref: /rk3399_rockchip-uboot/lib/strto.c (revision e4c5383e4d46ef196d022b481cab364bd3b9c877)
1*e4c5383eSSjoerd Simons /*
2*e4c5383eSSjoerd Simons  *  linux/lib/vsprintf.c
3*e4c5383eSSjoerd Simons  *
4*e4c5383eSSjoerd Simons  *  Copyright (C) 1991, 1992  Linus Torvalds
5*e4c5383eSSjoerd Simons  */
6*e4c5383eSSjoerd Simons 
7*e4c5383eSSjoerd Simons /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8*e4c5383eSSjoerd Simons /*
9*e4c5383eSSjoerd Simons  * Wirzenius wrote this portably, Torvalds fucked it up :-)
10*e4c5383eSSjoerd Simons  */
11*e4c5383eSSjoerd Simons 
12*e4c5383eSSjoerd Simons #include <common.h>
13*e4c5383eSSjoerd Simons #include <errno.h>
14*e4c5383eSSjoerd Simons #include <linux/ctype.h>
15*e4c5383eSSjoerd Simons 
16*e4c5383eSSjoerd Simons unsigned long simple_strtoul(const char *cp, char **endp,
17*e4c5383eSSjoerd Simons 				unsigned int base)
18*e4c5383eSSjoerd Simons {
19*e4c5383eSSjoerd Simons 	unsigned long result = 0;
20*e4c5383eSSjoerd Simons 	unsigned long value;
21*e4c5383eSSjoerd Simons 
22*e4c5383eSSjoerd Simons 	if (*cp == '0') {
23*e4c5383eSSjoerd Simons 		cp++;
24*e4c5383eSSjoerd Simons 		if ((*cp == 'x') && isxdigit(cp[1])) {
25*e4c5383eSSjoerd Simons 			base = 16;
26*e4c5383eSSjoerd Simons 			cp++;
27*e4c5383eSSjoerd Simons 		}
28*e4c5383eSSjoerd Simons 
29*e4c5383eSSjoerd Simons 		if (!base)
30*e4c5383eSSjoerd Simons 			base = 8;
31*e4c5383eSSjoerd Simons 	}
32*e4c5383eSSjoerd Simons 
33*e4c5383eSSjoerd Simons 	if (!base)
34*e4c5383eSSjoerd Simons 		base = 10;
35*e4c5383eSSjoerd Simons 
36*e4c5383eSSjoerd Simons 	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
37*e4c5383eSSjoerd Simons 	    ? toupper(*cp) : *cp)-'A'+10) < base) {
38*e4c5383eSSjoerd Simons 		result = result*base + value;
39*e4c5383eSSjoerd Simons 		cp++;
40*e4c5383eSSjoerd Simons 	}
41*e4c5383eSSjoerd Simons 
42*e4c5383eSSjoerd Simons 	if (endp)
43*e4c5383eSSjoerd Simons 		*endp = (char *)cp;
44*e4c5383eSSjoerd Simons 
45*e4c5383eSSjoerd Simons 	return result;
46*e4c5383eSSjoerd Simons }
47*e4c5383eSSjoerd Simons 
48*e4c5383eSSjoerd Simons int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
49*e4c5383eSSjoerd Simons {
50*e4c5383eSSjoerd Simons 	char *tail;
51*e4c5383eSSjoerd Simons 	unsigned long val;
52*e4c5383eSSjoerd Simons 	size_t len;
53*e4c5383eSSjoerd Simons 
54*e4c5383eSSjoerd Simons 	*res = 0;
55*e4c5383eSSjoerd Simons 	len = strlen(cp);
56*e4c5383eSSjoerd Simons 	if (len == 0)
57*e4c5383eSSjoerd Simons 		return -EINVAL;
58*e4c5383eSSjoerd Simons 
59*e4c5383eSSjoerd Simons 	val = simple_strtoul(cp, &tail, base);
60*e4c5383eSSjoerd Simons 	if (tail == cp)
61*e4c5383eSSjoerd Simons 		return -EINVAL;
62*e4c5383eSSjoerd Simons 
63*e4c5383eSSjoerd Simons 	if ((*tail == '\0') ||
64*e4c5383eSSjoerd Simons 		((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
65*e4c5383eSSjoerd Simons 		*res = val;
66*e4c5383eSSjoerd Simons 		return 0;
67*e4c5383eSSjoerd Simons 	}
68*e4c5383eSSjoerd Simons 
69*e4c5383eSSjoerd Simons 	return -EINVAL;
70*e4c5383eSSjoerd Simons }
71*e4c5383eSSjoerd Simons 
72*e4c5383eSSjoerd Simons long simple_strtol(const char *cp, char **endp, unsigned int base)
73*e4c5383eSSjoerd Simons {
74*e4c5383eSSjoerd Simons 	if (*cp == '-')
75*e4c5383eSSjoerd Simons 		return -simple_strtoul(cp + 1, endp, base);
76*e4c5383eSSjoerd Simons 
77*e4c5383eSSjoerd Simons 	return simple_strtoul(cp, endp, base);
78*e4c5383eSSjoerd Simons }
79*e4c5383eSSjoerd Simons 
80*e4c5383eSSjoerd Simons unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
81*e4c5383eSSjoerd Simons {
82*e4c5383eSSjoerd Simons 	unsigned long result = simple_strtoul(cp, endp, base);
83*e4c5383eSSjoerd Simons 	switch (**endp) {
84*e4c5383eSSjoerd Simons 	case 'G':
85*e4c5383eSSjoerd Simons 		result *= 1024;
86*e4c5383eSSjoerd Simons 		/* fall through */
87*e4c5383eSSjoerd Simons 	case 'M':
88*e4c5383eSSjoerd Simons 		result *= 1024;
89*e4c5383eSSjoerd Simons 		/* fall through */
90*e4c5383eSSjoerd Simons 	case 'K':
91*e4c5383eSSjoerd Simons 	case 'k':
92*e4c5383eSSjoerd Simons 		result *= 1024;
93*e4c5383eSSjoerd Simons 		if ((*endp)[1] == 'i') {
94*e4c5383eSSjoerd Simons 			if ((*endp)[2] == 'B')
95*e4c5383eSSjoerd Simons 				(*endp) += 3;
96*e4c5383eSSjoerd Simons 			else
97*e4c5383eSSjoerd Simons 				(*endp) += 2;
98*e4c5383eSSjoerd Simons 		}
99*e4c5383eSSjoerd Simons 	}
100*e4c5383eSSjoerd Simons 	return result;
101*e4c5383eSSjoerd Simons }
102*e4c5383eSSjoerd Simons 
103*e4c5383eSSjoerd Simons unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
104*e4c5383eSSjoerd Simons {
105*e4c5383eSSjoerd Simons 	unsigned long long result = simple_strtoull(cp, endp, base);
106*e4c5383eSSjoerd Simons 	switch (**endp) {
107*e4c5383eSSjoerd Simons 	case 'G':
108*e4c5383eSSjoerd Simons 		result *= 1024;
109*e4c5383eSSjoerd Simons 		/* fall through */
110*e4c5383eSSjoerd Simons 	case 'M':
111*e4c5383eSSjoerd Simons 		result *= 1024;
112*e4c5383eSSjoerd Simons 		/* fall through */
113*e4c5383eSSjoerd Simons 	case 'K':
114*e4c5383eSSjoerd Simons 	case 'k':
115*e4c5383eSSjoerd Simons 		result *= 1024;
116*e4c5383eSSjoerd Simons 		if ((*endp)[1] == 'i') {
117*e4c5383eSSjoerd Simons 			if ((*endp)[2] == 'B')
118*e4c5383eSSjoerd Simons 				(*endp) += 3;
119*e4c5383eSSjoerd Simons 			else
120*e4c5383eSSjoerd Simons 				(*endp) += 2;
121*e4c5383eSSjoerd Simons 		}
122*e4c5383eSSjoerd Simons 	}
123*e4c5383eSSjoerd Simons 	return result;
124*e4c5383eSSjoerd Simons }
125*e4c5383eSSjoerd Simons 
126*e4c5383eSSjoerd Simons unsigned long long simple_strtoull(const char *cp, char **endp,
127*e4c5383eSSjoerd Simons 					unsigned int base)
128*e4c5383eSSjoerd Simons {
129*e4c5383eSSjoerd Simons 	unsigned long long result = 0, value;
130*e4c5383eSSjoerd Simons 
131*e4c5383eSSjoerd Simons 	if (*cp == '0') {
132*e4c5383eSSjoerd Simons 		cp++;
133*e4c5383eSSjoerd Simons 		if ((*cp == 'x') && isxdigit(cp[1])) {
134*e4c5383eSSjoerd Simons 			base = 16;
135*e4c5383eSSjoerd Simons 			cp++;
136*e4c5383eSSjoerd Simons 		}
137*e4c5383eSSjoerd Simons 
138*e4c5383eSSjoerd Simons 		if (!base)
139*e4c5383eSSjoerd Simons 			base = 8;
140*e4c5383eSSjoerd Simons 	}
141*e4c5383eSSjoerd Simons 
142*e4c5383eSSjoerd Simons 	if (!base)
143*e4c5383eSSjoerd Simons 		base = 10;
144*e4c5383eSSjoerd Simons 
145*e4c5383eSSjoerd Simons 	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
146*e4c5383eSSjoerd Simons 		: (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
147*e4c5383eSSjoerd Simons 		result = result * base + value;
148*e4c5383eSSjoerd Simons 		cp++;
149*e4c5383eSSjoerd Simons 	}
150*e4c5383eSSjoerd Simons 
151*e4c5383eSSjoerd Simons 	if (endp)
152*e4c5383eSSjoerd Simons 		*endp = (char *) cp;
153*e4c5383eSSjoerd Simons 
154*e4c5383eSSjoerd Simons 	return result;
155*e4c5383eSSjoerd Simons }
156*e4c5383eSSjoerd Simons 
157*e4c5383eSSjoerd Simons long trailing_strtoln(const char *str, const char *end)
158*e4c5383eSSjoerd Simons {
159*e4c5383eSSjoerd Simons 	const char *p;
160*e4c5383eSSjoerd Simons 
161*e4c5383eSSjoerd Simons 	if (!end)
162*e4c5383eSSjoerd Simons 		end = str + strlen(str);
163*e4c5383eSSjoerd Simons 	for (p = end - 1; p > str; p--) {
164*e4c5383eSSjoerd Simons 		if (!isdigit(*p))
165*e4c5383eSSjoerd Simons 			return simple_strtoul(p + 1, NULL, 10);
166*e4c5383eSSjoerd Simons 	}
167*e4c5383eSSjoerd Simons 
168*e4c5383eSSjoerd Simons 	return -1;
169*e4c5383eSSjoerd Simons }
170*e4c5383eSSjoerd Simons 
171*e4c5383eSSjoerd Simons long trailing_strtol(const char *str)
172*e4c5383eSSjoerd Simons {
173*e4c5383eSSjoerd Simons 	return trailing_strtoln(str, NULL);
174*e4c5383eSSjoerd Simons }
175