3d77115d4d813af05713380dafdccbc14aaf1804
[oweals/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
38                                 if (!(var >= '0' && var <= '9'))
39                                         break;
40                         } while (var);
41                 }
42         }
43
44         if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
45                 s += 2;
46         return s;
47 }
48
49 unsigned long simple_strtoul(const char *cp, char **endp,
50                                 unsigned int base)
51 {
52         unsigned long result = 0;
53         unsigned long value;
54
55         cp = _parse_integer_fixup_radix(cp, &base);
56
57         while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
58             ? toupper(*cp) : *cp)-'A'+10) < base) {
59                 result = result*base + value;
60                 cp++;
61         }
62
63         if (endp)
64                 *endp = (char *)cp;
65
66         return result;
67 }
68
69 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
70 {
71         char *tail;
72         unsigned long val;
73         size_t len;
74
75         *res = 0;
76         len = strlen(cp);
77         if (len == 0)
78                 return -EINVAL;
79
80         val = simple_strtoul(cp, &tail, base);
81         if (tail == cp)
82                 return -EINVAL;
83
84         if ((*tail == '\0') ||
85                 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
86                 *res = val;
87                 return 0;
88         }
89
90         return -EINVAL;
91 }
92
93 long simple_strtol(const char *cp, char **endp, unsigned int base)
94 {
95         if (*cp == '-')
96                 return -simple_strtoul(cp + 1, endp, base);
97
98         return simple_strtoul(cp, endp, base);
99 }
100
101 unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
102 {
103         unsigned long result = simple_strtoul(cp, endp, base);
104         switch (tolower(**endp)) {
105         case 'g':
106                 result *= 1024;
107                 /* fall through */
108         case 'm':
109                 result *= 1024;
110                 /* fall through */
111         case 'k':
112                 result *= 1024;
113                 (*endp)++;
114                 if (**endp == 'i')
115                         (*endp)++;
116                 if (**endp == 'B')
117                         (*endp)++;
118         }
119         return result;
120 }
121
122 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
123 {
124         unsigned long long result = simple_strtoull(cp, endp, base);
125         switch (tolower(**endp)) {
126         case 'g':
127                 result *= 1024;
128                 /* fall through */
129         case 'm':
130                 result *= 1024;
131                 /* fall through */
132         case 'k':
133                 result *= 1024;
134                 (*endp)++;
135                 if (**endp == 'i')
136                         (*endp)++;
137                 if (**endp == 'B')
138                         (*endp)++;
139         }
140         return result;
141 }
142
143 unsigned long long simple_strtoull(const char *cp, char **endp,
144                                         unsigned int base)
145 {
146         unsigned long long result = 0, value;
147
148         cp = _parse_integer_fixup_radix(cp, &base);
149
150         while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
151                 : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
152                 result = result * base + value;
153                 cp++;
154         }
155
156         if (endp)
157                 *endp = (char *) cp;
158
159         return result;
160 }
161
162 long trailing_strtoln(const char *str, const char *end)
163 {
164         const char *p;
165
166         if (!end)
167                 end = str + strlen(str);
168         if (isdigit(end[-1])) {
169                 for (p = end - 1; p > str; p--) {
170                         if (!isdigit(*p))
171                                 return simple_strtoul(p + 1, NULL, 10);
172                 }
173         }
174
175         return -1;
176 }
177
178 long trailing_strtol(const char *str)
179 {
180         return trailing_strtoln(str, NULL);
181 }
182
183 void str_to_upper(const char *in, char *out, size_t len)
184 {
185         for (; len > 0 && *in; len--)
186                 *out++ = toupper(*in++);
187         if (len)
188                 *out = '\0';
189 }