1*d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*d30ea906Sjfb8856606  * Copyright(c) 2010-2014 Intel Corporation.
3*d30ea906Sjfb8856606  * Copyright(c) 2014 6WIND S.A.
4*d30ea906Sjfb8856606  */
5*d30ea906Sjfb8856606 
6*d30ea906Sjfb8856606 #include <stdlib.h>
7*d30ea906Sjfb8856606 #include <string.h>
8*d30ea906Sjfb8856606 #include <rte_log.h>
9*d30ea906Sjfb8856606 #include "parse.h"
10*d30ea906Sjfb8856606 
11*d30ea906Sjfb8856606 /*
12*d30ea906Sjfb8856606  * Parse elem, the elem could be single number/range or group
13*d30ea906Sjfb8856606  * 1) A single number elem, it's just a simple digit. e.g. 9
14*d30ea906Sjfb8856606  * 2) A single range elem, two digits with a '-' between. e.g. 2-6
15*d30ea906Sjfb8856606  * 3) A group elem, combines multiple 1) or 2) e.g 0,2-4,6
16*d30ea906Sjfb8856606  *    Within group, '-' used for a range separator;
17*d30ea906Sjfb8856606  *                       ',' used for a single number.
18*d30ea906Sjfb8856606  */
19*d30ea906Sjfb8856606 int
parse_set(const char * input,uint16_t set[],unsigned int num)20*d30ea906Sjfb8856606 parse_set(const char *input, uint16_t set[], unsigned int num)
21*d30ea906Sjfb8856606 {
22*d30ea906Sjfb8856606 	unsigned int idx;
23*d30ea906Sjfb8856606 	const char *str = input;
24*d30ea906Sjfb8856606 	char *end = NULL;
25*d30ea906Sjfb8856606 	unsigned int min, max;
26*d30ea906Sjfb8856606 
27*d30ea906Sjfb8856606 	memset(set, 0, num * sizeof(uint16_t));
28*d30ea906Sjfb8856606 
29*d30ea906Sjfb8856606 	while (isblank(*str))
30*d30ea906Sjfb8856606 		str++;
31*d30ea906Sjfb8856606 
32*d30ea906Sjfb8856606 	/* only digit or left bracket is qualify for start point */
33*d30ea906Sjfb8856606 	if (!isdigit(*str) || *str == '\0')
34*d30ea906Sjfb8856606 		return -1;
35*d30ea906Sjfb8856606 
36*d30ea906Sjfb8856606 	while (isblank(*str))
37*d30ea906Sjfb8856606 		str++;
38*d30ea906Sjfb8856606 	if (*str == '\0')
39*d30ea906Sjfb8856606 		return -1;
40*d30ea906Sjfb8856606 
41*d30ea906Sjfb8856606 	min = num;
42*d30ea906Sjfb8856606 	do {
43*d30ea906Sjfb8856606 
44*d30ea906Sjfb8856606 		/* go ahead to the first digit */
45*d30ea906Sjfb8856606 		while (isblank(*str))
46*d30ea906Sjfb8856606 			str++;
47*d30ea906Sjfb8856606 		if (!isdigit(*str))
48*d30ea906Sjfb8856606 			return -1;
49*d30ea906Sjfb8856606 
50*d30ea906Sjfb8856606 		/* get the digit value */
51*d30ea906Sjfb8856606 		errno = 0;
52*d30ea906Sjfb8856606 		idx = strtoul(str, &end, 10);
53*d30ea906Sjfb8856606 		if (errno || end == NULL || idx >= num)
54*d30ea906Sjfb8856606 			return -1;
55*d30ea906Sjfb8856606 
56*d30ea906Sjfb8856606 		/* go ahead to separator '-' and ',' */
57*d30ea906Sjfb8856606 		while (isblank(*end))
58*d30ea906Sjfb8856606 			end++;
59*d30ea906Sjfb8856606 		if (*end == '-') {
60*d30ea906Sjfb8856606 			if (min == num)
61*d30ea906Sjfb8856606 				min = idx;
62*d30ea906Sjfb8856606 			else /* avoid continuous '-' */
63*d30ea906Sjfb8856606 				return -1;
64*d30ea906Sjfb8856606 		} else if ((*end == ',') || (*end == '\0')) {
65*d30ea906Sjfb8856606 			max = idx;
66*d30ea906Sjfb8856606 
67*d30ea906Sjfb8856606 			if (min == num)
68*d30ea906Sjfb8856606 				min = idx;
69*d30ea906Sjfb8856606 
70*d30ea906Sjfb8856606 			for (idx = RTE_MIN(min, max);
71*d30ea906Sjfb8856606 					idx <= RTE_MAX(min, max); idx++) {
72*d30ea906Sjfb8856606 				set[idx] = 1;
73*d30ea906Sjfb8856606 			}
74*d30ea906Sjfb8856606 			min = num;
75*d30ea906Sjfb8856606 		} else
76*d30ea906Sjfb8856606 			return -1;
77*d30ea906Sjfb8856606 
78*d30ea906Sjfb8856606 		str = end + 1;
79*d30ea906Sjfb8856606 	} while (*end != '\0');
80*d30ea906Sjfb8856606 
81*d30ea906Sjfb8856606 	return str - input;
82*d30ea906Sjfb8856606 }
83