Merge https://gitlab.denx.de/u-boot/custodians/u-boot-x86
[platform/kernel/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 }