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