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