bootstd: Fix comment in bootmeth test
[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, uint *basep)
18 {
19         /* Look for a 0x prefix */
20         if (s[0] == '0') {
21                 int ch = tolower(s[1]);
22
23                 if (ch == 'x') {
24                         *basep = 16;
25                         s += 2;
26                 } else if (!*basep) {
27                         /* Only select octal if we don't have a base */
28                         *basep = 8;
29                 }
30         }
31
32         /* Use decimal by default */
33         if (!*basep)
34                 *basep = 10;
35
36         return s;
37 }
38
39 /**
40  * decode_digit() - Decode a single character into its numeric digit value
41  *
42  * This ignore case
43  *
44  * @ch: Character to convert (expects '0'..'9', 'a'..'f' or 'A'..'F')
45  * Return: value of digit (0..0xf) or 255 if the character is invalid
46  */
47 static uint decode_digit(int ch)
48 {
49         if (!isxdigit(ch))
50                 return 256;
51
52         ch = tolower(ch);
53
54         return ch <= '9' ? ch - '0' : ch - 'a' + 0xa;
55 }
56
57 ulong simple_strtoul(const char *cp, char **endp, uint base)
58 {
59         ulong result = 0;
60         uint value;
61
62         cp = _parse_integer_fixup_radix(cp, &base);
63
64         while (value = decode_digit(*cp), value < base) {
65                 result = result * base + value;
66                 cp++;
67         }
68
69         if (endp)
70                 *endp = (char *)cp;
71
72         return result;
73 }
74
75 ulong hextoul(const char *cp, char **endp)
76 {
77         return simple_strtoul(cp, endp, 16);
78 }
79
80 ulong dectoul(const char *cp, char **endp)
81 {
82         return simple_strtoul(cp, endp, 10);
83 }
84
85 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
86 {
87         char *tail;
88         unsigned long val;
89         size_t len;
90
91         *res = 0;
92         len = strlen(cp);
93         if (len == 0)
94                 return -EINVAL;
95
96         val = simple_strtoul(cp, &tail, base);
97         if (tail == cp)
98                 return -EINVAL;
99
100         if ((*tail == '\0') ||
101                 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
102                 *res = val;
103                 return 0;
104         }
105
106         return -EINVAL;
107 }
108
109 long simple_strtol(const char *cp, char **endp, unsigned int base)
110 {
111         if (*cp == '-')
112                 return -simple_strtoul(cp + 1, endp, base);
113
114         return simple_strtoul(cp, endp, base);
115 }
116
117 unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
118 {
119         unsigned long result = simple_strtoul(cp, endp, base);
120         switch (tolower(**endp)) {
121         case 'g':
122                 result *= 1024;
123                 /* fall through */
124         case 'm':
125                 result *= 1024;
126                 /* fall through */
127         case 'k':
128                 result *= 1024;
129                 (*endp)++;
130                 if (**endp == 'i')
131                         (*endp)++;
132                 if (**endp == 'B')
133                         (*endp)++;
134         }
135         return result;
136 }
137
138 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
139 {
140         unsigned long long result = simple_strtoull(cp, endp, base);
141         switch (tolower(**endp)) {
142         case 'g':
143                 result *= 1024;
144                 /* fall through */
145         case 'm':
146                 result *= 1024;
147                 /* fall through */
148         case 'k':
149                 result *= 1024;
150                 (*endp)++;
151                 if (**endp == 'i')
152                         (*endp)++;
153                 if (**endp == 'B')
154                         (*endp)++;
155         }
156         return result;
157 }
158
159 unsigned long long simple_strtoull(const char *cp, char **endp,
160                                         unsigned int base)
161 {
162         unsigned long long result = 0;
163         uint value;
164
165         cp = _parse_integer_fixup_radix(cp, &base);
166
167         while (value = decode_digit(*cp), value < base) {
168                 result = result * base + value;
169                 cp++;
170         }
171
172         if (endp)
173                 *endp = (char *) cp;
174
175         return result;
176 }
177
178 long long simple_strtoll(const char *cp, char **endp, unsigned int base)
179 {
180         if (*cp == '-')
181                 return -simple_strtoull(cp + 1, endp, base);
182
183         return simple_strtoull(cp, endp, base);
184 }
185
186 long trailing_strtoln_end(const char *str, const char *end, char const **endp)
187 {
188         const char *p;
189
190         if (!end)
191                 end = str + strlen(str);
192         p = end - 1;
193         if (p > str && isdigit(*p)) {
194                 do {
195                         if (!isdigit(p[-1])) {
196                                 if (endp)
197                                         *endp = p;
198                                 return dectoul(p, NULL);
199                         }
200                 } while (--p > str);
201         }
202         if (endp)
203                 *endp = end;
204
205         return -1;
206 }
207
208 long trailing_strtoln(const char *str, const char *end)
209 {
210         return trailing_strtoln_end(str, end, NULL);
211 }
212
213 long trailing_strtol(const char *str)
214 {
215         return trailing_strtoln(str, NULL);
216 }
217
218 void str_to_upper(const char *in, char *out, size_t len)
219 {
220         for (; len > 0 && *in; len--)
221                 *out++ = toupper(*in++);
222         if (len)
223                 *out = '\0';
224 }