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