]> git.ipfire.org Git - thirdparty/u-boot.git/blob - lib/strto.c
Merge tag 'u-boot-amlogic-20200406' of https://gitlab.denx.de/u-boot/custodians/u...
[thirdparty/u-boot.git] / lib / strto.c
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 /* from lib/kstrtox.c */
17 static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
18 {
19 if (*base == 0) {
20 if (s[0] == '0') {
21 if (tolower(s[1]) == 'x' && isxdigit(s[2]))
22 *base = 16;
23 else
24 *base = 8;
25 } else {
26 int i = 0;
27 char var;
28
29 *base = 10;
30
31 do {
32 var = tolower(s[i++]);
33 if (var >= 'a' && var <= 'f') {
34 *base = 16;
35 break;
36 }
37 } while (var);
38 }
39 }
40
41 if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
42 s += 2;
43 return s;
44 }
45
46 unsigned long simple_strtoul(const char *cp, char **endp,
47 unsigned int base)
48 {
49 unsigned long result = 0;
50 unsigned long value;
51
52 cp = _parse_integer_fixup_radix(cp, &base);
53
54 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
55 ? toupper(*cp) : *cp)-'A'+10) < base) {
56 result = result*base + value;
57 cp++;
58 }
59
60 if (endp)
61 *endp = (char *)cp;
62
63 return result;
64 }
65
66 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
67 {
68 char *tail;
69 unsigned long val;
70 size_t len;
71
72 *res = 0;
73 len = strlen(cp);
74 if (len == 0)
75 return -EINVAL;
76
77 val = simple_strtoul(cp, &tail, base);
78 if (tail == cp)
79 return -EINVAL;
80
81 if ((*tail == '\0') ||
82 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
83 *res = val;
84 return 0;
85 }
86
87 return -EINVAL;
88 }
89
90 long simple_strtol(const char *cp, char **endp, unsigned int base)
91 {
92 if (*cp == '-')
93 return -simple_strtoul(cp + 1, endp, base);
94
95 return simple_strtoul(cp, endp, base);
96 }
97
98 unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
99 {
100 unsigned long result = simple_strtoul(cp, endp, base);
101 switch (tolower(**endp)) {
102 case 'g':
103 result *= 1024;
104 /* fall through */
105 case 'm':
106 result *= 1024;
107 /* fall through */
108 case 'k':
109 result *= 1024;
110 (*endp)++;
111 if (**endp == 'i')
112 (*endp)++;
113 if (**endp == 'B')
114 (*endp)++;
115 }
116 return result;
117 }
118
119 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
120 {
121 unsigned long long result = simple_strtoull(cp, endp, base);
122 switch (tolower(**endp)) {
123 case 'g':
124 result *= 1024;
125 /* fall through */
126 case 'm':
127 result *= 1024;
128 /* fall through */
129 case 'k':
130 result *= 1024;
131 (*endp)++;
132 if (**endp == 'i')
133 (*endp)++;
134 if (**endp == 'B')
135 (*endp)++;
136 }
137 return result;
138 }
139
140 unsigned long long simple_strtoull(const char *cp, char **endp,
141 unsigned int base)
142 {
143 unsigned long long result = 0, value;
144
145 cp = _parse_integer_fixup_radix(cp, &base);
146
147 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
148 : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
149 result = result * base + value;
150 cp++;
151 }
152
153 if (endp)
154 *endp = (char *) cp;
155
156 return result;
157 }
158
159 long trailing_strtoln(const char *str, const char *end)
160 {
161 const char *p;
162
163 if (!end)
164 end = str + strlen(str);
165 if (isdigit(end[-1])) {
166 for (p = end - 1; p > str; p--) {
167 if (!isdigit(*p))
168 return simple_strtoul(p + 1, NULL, 10);
169 }
170 }
171
172 return -1;
173 }
174
175 long trailing_strtol(const char *str)
176 {
177 return trailing_strtoln(str, NULL);
178 }