net: tsec: Make live-tree compatible
[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 (**endp) {
89         case 'G':
90                 result *= 1024;
91                 /* fall through */
92         case 'M':
93                 result *= 1024;
94                 /* fall through */
95         case 'K':
96         case 'k':
97                 result *= 1024;
98                 if ((*endp)[1] == 'i') {
99                         if ((*endp)[2] == 'B')
100                                 (*endp) += 3;
101                         else
102                                 (*endp) += 2;
103                 }
104         }
105         return result;
106 }
107
108 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
109 {
110         unsigned long long result = simple_strtoull(cp, endp, base);
111         switch (**endp) {
112         case 'G':
113                 result *= 1024;
114                 /* fall through */
115         case 'M':
116                 result *= 1024;
117                 /* fall through */
118         case 'K':
119         case 'k':
120                 result *= 1024;
121                 if ((*endp)[1] == 'i') {
122                         if ((*endp)[2] == 'B')
123                                 (*endp) += 3;
124                         else
125                                 (*endp) += 2;
126                 }
127         }
128         return result;
129 }
130
131 unsigned long long simple_strtoull(const char *cp, char **endp,
132                                         unsigned int base)
133 {
134         unsigned long long result = 0, value;
135
136         cp = _parse_integer_fixup_radix(cp, &base);
137
138         while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
139                 : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
140                 result = result * base + value;
141                 cp++;
142         }
143
144         if (endp)
145                 *endp = (char *) cp;
146
147         return result;
148 }
149
150 long trailing_strtoln(const char *str, const char *end)
151 {
152         const char *p;
153
154         if (!end)
155                 end = str + strlen(str);
156         if (isdigit(end[-1])) {
157                 for (p = end - 1; p > str; p--) {
158                         if (!isdigit(*p))
159                                 return simple_strtoul(p + 1, NULL, 10);
160                 }
161         }
162
163         return -1;
164 }
165
166 long trailing_strtol(const char *str)
167 {
168         return trailing_strtoln(str, NULL);
169 }