1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Based on intlist.c by:
4*4882a593Smuzhiyun * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <errno.h>
8*4882a593Smuzhiyun #include <stdlib.h>
9*4882a593Smuzhiyun #include <linux/compiler.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include "intlist.h"
12*4882a593Smuzhiyun
intlist__node_new(struct rblist * rblist __maybe_unused,const void * entry)13*4882a593Smuzhiyun static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused,
14*4882a593Smuzhiyun const void *entry)
15*4882a593Smuzhiyun {
16*4882a593Smuzhiyun int i = (int)((long)entry);
17*4882a593Smuzhiyun struct rb_node *rc = NULL;
18*4882a593Smuzhiyun struct int_node *node = malloc(sizeof(*node));
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun if (node != NULL) {
21*4882a593Smuzhiyun node->i = i;
22*4882a593Smuzhiyun node->priv = NULL;
23*4882a593Smuzhiyun rc = &node->rb_node;
24*4882a593Smuzhiyun }
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun return rc;
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun
int_node__delete(struct int_node * ilist)29*4882a593Smuzhiyun static void int_node__delete(struct int_node *ilist)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun free(ilist);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun
intlist__node_delete(struct rblist * rblist __maybe_unused,struct rb_node * rb_node)34*4882a593Smuzhiyun static void intlist__node_delete(struct rblist *rblist __maybe_unused,
35*4882a593Smuzhiyun struct rb_node *rb_node)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun struct int_node *node = container_of(rb_node, struct int_node, rb_node);
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun int_node__delete(node);
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun
intlist__node_cmp(struct rb_node * rb_node,const void * entry)42*4882a593Smuzhiyun static int intlist__node_cmp(struct rb_node *rb_node, const void *entry)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun int i = (int)((long)entry);
45*4882a593Smuzhiyun struct int_node *node = container_of(rb_node, struct int_node, rb_node);
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun return node->i - i;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
intlist__add(struct intlist * ilist,int i)50*4882a593Smuzhiyun int intlist__add(struct intlist *ilist, int i)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun return rblist__add_node(&ilist->rblist, (void *)((long)i));
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
intlist__remove(struct intlist * ilist,struct int_node * node)55*4882a593Smuzhiyun void intlist__remove(struct intlist *ilist, struct int_node *node)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun rblist__remove_node(&ilist->rblist, &node->rb_node);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
__intlist__findnew(struct intlist * ilist,int i,bool create)60*4882a593Smuzhiyun static struct int_node *__intlist__findnew(struct intlist *ilist,
61*4882a593Smuzhiyun int i, bool create)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun struct int_node *node = NULL;
64*4882a593Smuzhiyun struct rb_node *rb_node;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun if (ilist == NULL)
67*4882a593Smuzhiyun return NULL;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun if (create)
70*4882a593Smuzhiyun rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i));
71*4882a593Smuzhiyun else
72*4882a593Smuzhiyun rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun if (rb_node)
75*4882a593Smuzhiyun node = container_of(rb_node, struct int_node, rb_node);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun return node;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
intlist__find(struct intlist * ilist,int i)80*4882a593Smuzhiyun struct int_node *intlist__find(struct intlist *ilist, int i)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun return __intlist__findnew(ilist, i, false);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
intlist__findnew(struct intlist * ilist,int i)85*4882a593Smuzhiyun struct int_node *intlist__findnew(struct intlist *ilist, int i)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun return __intlist__findnew(ilist, i, true);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
intlist__parse_list(struct intlist * ilist,const char * s)90*4882a593Smuzhiyun static int intlist__parse_list(struct intlist *ilist, const char *s)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun char *sep;
93*4882a593Smuzhiyun int err;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun do {
96*4882a593Smuzhiyun long value = strtol(s, &sep, 10);
97*4882a593Smuzhiyun err = -EINVAL;
98*4882a593Smuzhiyun if (*sep != ',' && *sep != '\0')
99*4882a593Smuzhiyun break;
100*4882a593Smuzhiyun err = intlist__add(ilist, value);
101*4882a593Smuzhiyun if (err)
102*4882a593Smuzhiyun break;
103*4882a593Smuzhiyun s = sep + 1;
104*4882a593Smuzhiyun } while (*sep != '\0');
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun return err;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
intlist__new(const char * slist)109*4882a593Smuzhiyun struct intlist *intlist__new(const char *slist)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun struct intlist *ilist = malloc(sizeof(*ilist));
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun if (ilist != NULL) {
114*4882a593Smuzhiyun rblist__init(&ilist->rblist);
115*4882a593Smuzhiyun ilist->rblist.node_cmp = intlist__node_cmp;
116*4882a593Smuzhiyun ilist->rblist.node_new = intlist__node_new;
117*4882a593Smuzhiyun ilist->rblist.node_delete = intlist__node_delete;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun if (slist && intlist__parse_list(ilist, slist))
120*4882a593Smuzhiyun goto out_delete;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun return ilist;
124*4882a593Smuzhiyun out_delete:
125*4882a593Smuzhiyun intlist__delete(ilist);
126*4882a593Smuzhiyun return NULL;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
intlist__delete(struct intlist * ilist)129*4882a593Smuzhiyun void intlist__delete(struct intlist *ilist)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun if (ilist != NULL)
132*4882a593Smuzhiyun rblist__delete(&ilist->rblist);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
intlist__entry(const struct intlist * ilist,unsigned int idx)135*4882a593Smuzhiyun struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun struct int_node *node = NULL;
138*4882a593Smuzhiyun struct rb_node *rb_node;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun rb_node = rblist__entry(&ilist->rblist, idx);
141*4882a593Smuzhiyun if (rb_node)
142*4882a593Smuzhiyun node = container_of(rb_node, struct int_node, rb_node);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun return node;
145*4882a593Smuzhiyun }
146