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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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