blob: 57d62163da486f7957c97d9038fb92aadab65050 [file] [log] [blame]
Sjoerd Simonse4c53832015-12-04 23:27:39 +01001/*
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
Rob Clark2e794612017-09-11 16:53:08 -040016/* from lib/kstrtox.c */
17static 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;
Sean Anderson1fae7412020-06-07 01:36:45 -040025 } else
Rob Clark2e794612017-09-11 16:53:08 -040026 *base = 10;
27 }
28 if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
29 s += 2;
30 return s;
31}
32
Simon Glass7e5f4602021-07-24 09:03:29 -060033ulong simple_strtoul(const char *cp, char **endp, uint base)
Sjoerd Simonse4c53832015-12-04 23:27:39 +010034{
Simon Glass7e5f4602021-07-24 09:03:29 -060035 ulong result = 0;
36 ulong value;
Sjoerd Simonse4c53832015-12-04 23:27:39 +010037
Rob Clark2e794612017-09-11 16:53:08 -040038 cp = _parse_integer_fixup_radix(cp, &base);
Sjoerd Simonse4c53832015-12-04 23:27:39 +010039
40 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
41 ? toupper(*cp) : *cp)-'A'+10) < base) {
42 result = result*base + value;
43 cp++;
44 }
45
46 if (endp)
47 *endp = (char *)cp;
48
49 return result;
50}
51
Simon Glass7e5f4602021-07-24 09:03:29 -060052ulong hextoul(const char *cp, char **endp)
53{
54 return simple_strtoul(cp, endp, 16);
55}
56
Sjoerd Simonse4c53832015-12-04 23:27:39 +010057int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
58{
59 char *tail;
60 unsigned long val;
61 size_t len;
62
63 *res = 0;
64 len = strlen(cp);
65 if (len == 0)
66 return -EINVAL;
67
68 val = simple_strtoul(cp, &tail, base);
69 if (tail == cp)
70 return -EINVAL;
71
72 if ((*tail == '\0') ||
73 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
74 *res = val;
75 return 0;
76 }
77
78 return -EINVAL;
79}
80
81long simple_strtol(const char *cp, char **endp, unsigned int base)
82{
83 if (*cp == '-')
84 return -simple_strtoul(cp + 1, endp, base);
85
86 return simple_strtoul(cp, endp, base);
87}
88
89unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
90{
91 unsigned long result = simple_strtoul(cp, endp, base);
Miquel Raynala353e6a2018-09-06 09:08:43 +020092 switch (tolower(**endp)) {
93 case 'g':
Sjoerd Simonse4c53832015-12-04 23:27:39 +010094 result *= 1024;
95 /* fall through */
Miquel Raynala353e6a2018-09-06 09:08:43 +020096 case 'm':
Sjoerd Simonse4c53832015-12-04 23:27:39 +010097 result *= 1024;
98 /* fall through */
Sjoerd Simonse4c53832015-12-04 23:27:39 +010099 case 'k':
100 result *= 1024;
Miquel Raynalb87b0d82018-09-06 09:08:44 +0200101 (*endp)++;
102 if (**endp == 'i')
103 (*endp)++;
104 if (**endp == 'B')
105 (*endp)++;
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100106 }
107 return result;
108}
109
110unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
111{
112 unsigned long long result = simple_strtoull(cp, endp, base);
Miquel Raynala353e6a2018-09-06 09:08:43 +0200113 switch (tolower(**endp)) {
114 case 'g':
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100115 result *= 1024;
116 /* fall through */
Miquel Raynala353e6a2018-09-06 09:08:43 +0200117 case 'm':
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100118 result *= 1024;
119 /* fall through */
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100120 case 'k':
121 result *= 1024;
Miquel Raynalb87b0d82018-09-06 09:08:44 +0200122 (*endp)++;
123 if (**endp == 'i')
124 (*endp)++;
125 if (**endp == 'B')
126 (*endp)++;
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100127 }
128 return result;
129}
130
131unsigned long long simple_strtoull(const char *cp, char **endp,
132 unsigned int base)
133{
134 unsigned long long result = 0, value;
135
Rob Clark2e794612017-09-11 16:53:08 -0400136 cp = _parse_integer_fixup_radix(cp, &base);
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100137
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
Roland Gaudig0b016422021-07-23 12:29:18 +0000150long long simple_strtoll(const char *cp, char **endp, unsigned int base)
151{
152 if (*cp == '-')
153 return -simple_strtoull(cp + 1, endp, base);
154
155 return simple_strtoull(cp, endp, base);
156}
157
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100158long trailing_strtoln(const char *str, const char *end)
159{
160 const char *p;
161
162 if (!end)
163 end = str + strlen(str);
Simon Glassb91c6a12016-10-05 20:42:11 -0600164 if (isdigit(end[-1])) {
165 for (p = end - 1; p > str; p--) {
166 if (!isdigit(*p))
167 return simple_strtoul(p + 1, NULL, 10);
168 }
Sjoerd Simonse4c53832015-12-04 23:27:39 +0100169 }
170
171 return -1;
172}
173
174long trailing_strtol(const char *str)
175{
176 return trailing_strtoln(str, NULL);
177}
Simon Glassfdc79a62020-04-08 08:32:56 -0600178
179void str_to_upper(const char *in, char *out, size_t len)
180{
181 for (; len > 0 && *in; len--)
182 *out++ = toupper(*in++);
183 if (len)
184 *out = '\0';
185}