1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2016 Intel Corporation.
3 * Copyright (c) 2017 Cavium, Inc.
4 * Copyright (c) 2022 Marvell.
5 */
6
7 #include <ctype.h>
8 #include <errno.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include <rte_common.h>
15 #include <rte_string_fns.h>
16
17 #include "parser.h"
18
19 static uint32_t
get_hex_val(char c)20 get_hex_val(char c)
21 {
22 switch (c) {
23 case '0':
24 case '1':
25 case '2':
26 case '3':
27 case '4':
28 case '5':
29 case '6':
30 case '7':
31 case '8':
32 case '9':
33 return c - '0';
34 case 'A':
35 case 'B':
36 case 'C':
37 case 'D':
38 case 'E':
39 case 'F':
40 return c - 'A' + 10;
41 case 'a':
42 case 'b':
43 case 'c':
44 case 'd':
45 case 'e':
46 case 'f':
47 return c - 'a' + 10;
48 default:
49 return 0;
50 }
51 }
52
53 int
parser_read_arg_bool(const char * p)54 parser_read_arg_bool(const char *p)
55 {
56 p = rte_str_skip_leading_spaces(p);
57 int result = -EINVAL;
58
59 if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
60 ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
61 p += 3;
62 result = 1;
63 }
64
65 if (((p[0] == 'o') && (p[1] == 'n')) || ((p[0] == 'O') && (p[1] == 'N'))) {
66 p += 2;
67 result = 1;
68 }
69
70 if (((p[0] == 'n') && (p[1] == 'o')) || ((p[0] == 'N') && (p[1] == 'O'))) {
71 p += 2;
72 result = 0;
73 }
74
75 if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
76 ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
77 p += 3;
78 result = 0;
79 }
80
81 p = rte_str_skip_leading_spaces(p);
82
83 if (p[0] != '\0')
84 return -EINVAL;
85
86 return result;
87 }
88
89 int
parser_read_uint64(uint64_t * value,const char * p)90 parser_read_uint64(uint64_t *value, const char *p)
91 {
92 char *next;
93 uint64_t val;
94
95 p = rte_str_skip_leading_spaces(p);
96 if (!isdigit(*p))
97 return -EINVAL;
98
99 val = strtoul(p, &next, 10);
100 if (p == next)
101 return -EINVAL;
102
103 p = next;
104 switch (*p) {
105 case 'T':
106 val *= 1024ULL;
107 /* fall through */
108 case 'G':
109 val *= 1024ULL;
110 /* fall through */
111 case 'M':
112 val *= 1024ULL;
113 /* fall through */
114 case 'k':
115 case 'K':
116 val *= 1024ULL;
117 p++;
118 break;
119 }
120
121 p = rte_str_skip_leading_spaces(p);
122 if (*p != '\0')
123 return -EINVAL;
124
125 *value = val;
126 return 0;
127 }
128
129 int
parser_read_int32(int32_t * value,const char * p)130 parser_read_int32(int32_t *value, const char *p)
131 {
132 char *next;
133 int32_t val;
134
135 p = rte_str_skip_leading_spaces(p);
136 if ((*p != '-') && (!isdigit(*p)))
137 return -EINVAL;
138
139 val = strtol(p, &next, 10);
140 if ((*next != '\0') || (p == next))
141 return -EINVAL;
142
143 *value = val;
144 return 0;
145 }
146
147 int
parser_read_int16(int16_t * value,const char * p)148 parser_read_int16(int16_t *value, const char *p)
149 {
150 char *next;
151 int16_t val;
152
153 p = rte_str_skip_leading_spaces(p);
154 if ((*p != '-') && (!isdigit(*p)))
155 return -EINVAL;
156
157 val = strtol(p, &next, 10);
158 if ((*next != '\0') || (p == next))
159 return -EINVAL;
160
161 *value = val;
162 return 0;
163 }
164
165 int
parser_read_uint64_hex(uint64_t * value,const char * p)166 parser_read_uint64_hex(uint64_t *value, const char *p)
167 {
168 char *next;
169 uint64_t val;
170
171 p = rte_str_skip_leading_spaces(p);
172
173 val = strtoul(p, &next, 16);
174 if (p == next)
175 return -EINVAL;
176
177 p = rte_str_skip_leading_spaces(next);
178 if (*p != '\0')
179 return -EINVAL;
180
181 *value = val;
182 return 0;
183 }
184
185 int
parser_read_uint32(uint32_t * value,const char * p)186 parser_read_uint32(uint32_t *value, const char *p)
187 {
188 uint64_t val = 0;
189 int ret = parser_read_uint64(&val, p);
190
191 if (ret < 0)
192 return ret;
193
194 if (val > UINT32_MAX)
195 return -ERANGE;
196
197 *value = val;
198 return 0;
199 }
200
201 int
parser_read_uint32_hex(uint32_t * value,const char * p)202 parser_read_uint32_hex(uint32_t *value, const char *p)
203 {
204 uint64_t val = 0;
205 int ret = parser_read_uint64_hex(&val, p);
206
207 if (ret < 0)
208 return ret;
209
210 if (val > UINT32_MAX)
211 return -ERANGE;
212
213 *value = val;
214 return 0;
215 }
216
217 int
parser_read_uint16(uint16_t * value,const char * p)218 parser_read_uint16(uint16_t *value, const char *p)
219 {
220 uint64_t val = 0;
221 int ret = parser_read_uint64(&val, p);
222
223 if (ret < 0)
224 return ret;
225
226 if (val > UINT16_MAX)
227 return -ERANGE;
228
229 *value = val;
230 return 0;
231 }
232
233 int
parser_read_uint16_hex(uint16_t * value,const char * p)234 parser_read_uint16_hex(uint16_t *value, const char *p)
235 {
236 uint64_t val = 0;
237 int ret = parser_read_uint64_hex(&val, p);
238
239 if (ret < 0)
240 return ret;
241
242 if (val > UINT16_MAX)
243 return -ERANGE;
244
245 *value = val;
246 return 0;
247 }
248
249 int
parser_read_uint8(uint8_t * value,const char * p)250 parser_read_uint8(uint8_t *value, const char *p)
251 {
252 uint64_t val = 0;
253 int ret = parser_read_uint64(&val, p);
254
255 if (ret < 0)
256 return ret;
257
258 if (val > UINT8_MAX)
259 return -ERANGE;
260
261 *value = val;
262 return 0;
263 }
264
265 int
parser_read_uint8_hex(uint8_t * value,const char * p)266 parser_read_uint8_hex(uint8_t *value, const char *p)
267 {
268 uint64_t val = 0;
269 int ret = parser_read_uint64_hex(&val, p);
270
271 if (ret < 0)
272 return ret;
273
274 if (val > UINT8_MAX)
275 return -ERANGE;
276
277 *value = val;
278 return 0;
279 }
280
281 int
parse_tokenize_string(char * string,char * tokens[],uint32_t * n_tokens)282 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
283 {
284 uint32_t i;
285
286 if ((string == NULL) || (tokens == NULL) || (*n_tokens < 1))
287 return -EINVAL;
288
289 for (i = 0; i < *n_tokens; i++) {
290 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
291 if (tokens[i] == NULL)
292 break;
293 }
294
295 if ((i == *n_tokens) && (strtok_r(string, PARSE_DELIMITER, &string) != NULL))
296 return -E2BIG;
297
298 *n_tokens = i;
299 return 0;
300 }
301
302 int
parse_hex_string(char * src,uint8_t * dst,uint32_t * size)303 parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
304 {
305 char *c;
306 uint32_t len, i;
307
308 /* Check input parameters */
309 if ((src == NULL) || (dst == NULL) || (size == NULL) || (*size == 0))
310 return -1;
311
312 len = strlen(src);
313 if (((len & 3) != 0) || (len > (*size) * 2))
314 return -1;
315 *size = len / 2;
316
317 for (c = src; *c != 0; c++) {
318 if ((((*c) >= '0') && ((*c) <= '9')) || (((*c) >= 'A') && ((*c) <= 'F')) ||
319 (((*c) >= 'a') && ((*c) <= 'f')))
320 continue;
321
322 return -1;
323 }
324
325 /* Convert chars to bytes */
326 for (i = 0; i < *size; i++)
327 dst[i] = get_hex_val(src[2 * i]) * 16 + get_hex_val(src[2 * i + 1]);
328
329 return 0;
330 }
331
332 int
parse_lcores_list(bool lcores[],int lcores_num,const char * corelist)333 parse_lcores_list(bool lcores[], int lcores_num, const char *corelist)
334 {
335 int i, idx = 0;
336 int min, max;
337 char *end = NULL;
338
339 if (corelist == NULL)
340 return -1;
341 while (isblank(*corelist))
342 corelist++;
343 i = strlen(corelist);
344 while ((i > 0) && isblank(corelist[i - 1]))
345 i--;
346
347 /* Get list of lcores */
348 min = RTE_MAX_LCORE;
349 do {
350 while (isblank(*corelist))
351 corelist++;
352 if (*corelist == '\0')
353 return -1;
354 idx = strtoul(corelist, &end, 10);
355 if (idx < 0 || idx > lcores_num)
356 return -1;
357
358 if (end == NULL)
359 return -1;
360 while (isblank(*end))
361 end++;
362 if (*end == '-') {
363 min = idx;
364 } else if ((*end == ',') || (*end == '\0')) {
365 max = idx;
366 if (min == RTE_MAX_LCORE)
367 min = idx;
368 for (idx = min; idx <= max; idx++) {
369 if (lcores[idx] == 1)
370 return -E2BIG;
371 lcores[idx] = 1;
372 }
373
374 min = RTE_MAX_LCORE;
375 } else
376 return -1;
377 corelist = end + 1;
378 } while (*end != '\0');
379
380 return 0;
381 }
382