15efdfe75SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
270b40c4aSDavid Ahern /*
370b40c4aSDavid Ahern * Based on intlist.c by:
470b40c4aSDavid Ahern * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
570b40c4aSDavid Ahern */
670b40c4aSDavid Ahern
770b40c4aSDavid Ahern #include <errno.h>
870b40c4aSDavid Ahern #include <stdlib.h>
970b40c4aSDavid Ahern #include <linux/compiler.h>
1070b40c4aSDavid Ahern
1170b40c4aSDavid Ahern #include "intlist.h"
1270b40c4aSDavid Ahern
intlist__node_new(struct rblist * rblist __maybe_unused,const void * entry)131d037ca1SIrina Tirdea static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused,
1470b40c4aSDavid Ahern const void *entry)
1570b40c4aSDavid Ahern {
16*94253393SJin Yao unsigned long i = (unsigned long)entry;
1770b40c4aSDavid Ahern struct rb_node *rc = NULL;
1870b40c4aSDavid Ahern struct int_node *node = malloc(sizeof(*node));
1970b40c4aSDavid Ahern
2070b40c4aSDavid Ahern if (node != NULL) {
2170b40c4aSDavid Ahern node->i = i;
222969b129SDavid Ahern node->priv = NULL;
2370b40c4aSDavid Ahern rc = &node->rb_node;
2470b40c4aSDavid Ahern }
2570b40c4aSDavid Ahern
2670b40c4aSDavid Ahern return rc;
2770b40c4aSDavid Ahern }
2870b40c4aSDavid Ahern
int_node__delete(struct int_node * ilist)2970b40c4aSDavid Ahern static void int_node__delete(struct int_node *ilist)
3070b40c4aSDavid Ahern {
3170b40c4aSDavid Ahern free(ilist);
3270b40c4aSDavid Ahern }
3370b40c4aSDavid Ahern
intlist__node_delete(struct rblist * rblist __maybe_unused,struct rb_node * rb_node)341d037ca1SIrina Tirdea static void intlist__node_delete(struct rblist *rblist __maybe_unused,
3570b40c4aSDavid Ahern struct rb_node *rb_node)
3670b40c4aSDavid Ahern {
3770b40c4aSDavid Ahern struct int_node *node = container_of(rb_node, struct int_node, rb_node);
3870b40c4aSDavid Ahern
3970b40c4aSDavid Ahern int_node__delete(node);
4070b40c4aSDavid Ahern }
4170b40c4aSDavid Ahern
intlist__node_cmp(struct rb_node * rb_node,const void * entry)4270b40c4aSDavid Ahern static int intlist__node_cmp(struct rb_node *rb_node, const void *entry)
4370b40c4aSDavid Ahern {
44*94253393SJin Yao unsigned long i = (unsigned long)entry;
4570b40c4aSDavid Ahern struct int_node *node = container_of(rb_node, struct int_node, rb_node);
4670b40c4aSDavid Ahern
47*94253393SJin Yao if (node->i > i)
48*94253393SJin Yao return 1;
49*94253393SJin Yao else if (node->i < i)
50*94253393SJin Yao return -1;
51*94253393SJin Yao
52*94253393SJin Yao return 0;
5370b40c4aSDavid Ahern }
5470b40c4aSDavid Ahern
intlist__add(struct intlist * ilist,unsigned long i)55*94253393SJin Yao int intlist__add(struct intlist *ilist, unsigned long i)
5670b40c4aSDavid Ahern {
57*94253393SJin Yao return rblist__add_node(&ilist->rblist, (void *)i);
5870b40c4aSDavid Ahern }
5970b40c4aSDavid Ahern
intlist__remove(struct intlist * ilist,struct int_node * node)6060ebf328SSuzuki K. Poulose void intlist__remove(struct intlist *ilist, struct int_node *node)
6170b40c4aSDavid Ahern {
6260ebf328SSuzuki K. Poulose rblist__remove_node(&ilist->rblist, &node->rb_node);
6370b40c4aSDavid Ahern }
6470b40c4aSDavid Ahern
__intlist__findnew(struct intlist * ilist,unsigned long i,bool create)65813335b8SDavid Ahern static struct int_node *__intlist__findnew(struct intlist *ilist,
66*94253393SJin Yao unsigned long i, bool create)
6770b40c4aSDavid Ahern {
68813335b8SDavid Ahern struct int_node *node = NULL;
695a3d04d6SArnaldo Carvalho de Melo struct rb_node *rb_node;
7070b40c4aSDavid Ahern
715a3d04d6SArnaldo Carvalho de Melo if (ilist == NULL)
725a3d04d6SArnaldo Carvalho de Melo return NULL;
735a3d04d6SArnaldo Carvalho de Melo
74813335b8SDavid Ahern if (create)
75*94253393SJin Yao rb_node = rblist__findnew(&ilist->rblist, (void *)i);
76813335b8SDavid Ahern else
77*94253393SJin Yao rb_node = rblist__find(&ilist->rblist, (void *)i);
78813335b8SDavid Ahern
7970b40c4aSDavid Ahern if (rb_node)
8070b40c4aSDavid Ahern node = container_of(rb_node, struct int_node, rb_node);
8170b40c4aSDavid Ahern
8270b40c4aSDavid Ahern return node;
8370b40c4aSDavid Ahern }
8470b40c4aSDavid Ahern
intlist__find(struct intlist * ilist,unsigned long i)85*94253393SJin Yao struct int_node *intlist__find(struct intlist *ilist, unsigned long i)
86813335b8SDavid Ahern {
87813335b8SDavid Ahern return __intlist__findnew(ilist, i, false);
88813335b8SDavid Ahern }
89813335b8SDavid Ahern
intlist__findnew(struct intlist * ilist,unsigned long i)90*94253393SJin Yao struct int_node *intlist__findnew(struct intlist *ilist, unsigned long i)
91813335b8SDavid Ahern {
92813335b8SDavid Ahern return __intlist__findnew(ilist, i, true);
93813335b8SDavid Ahern }
94813335b8SDavid Ahern
intlist__parse_list(struct intlist * ilist,const char * s)95ffe0fb76SArnaldo Carvalho de Melo static int intlist__parse_list(struct intlist *ilist, const char *s)
96ffe0fb76SArnaldo Carvalho de Melo {
97ffe0fb76SArnaldo Carvalho de Melo char *sep;
98ffe0fb76SArnaldo Carvalho de Melo int err;
99ffe0fb76SArnaldo Carvalho de Melo
100ffe0fb76SArnaldo Carvalho de Melo do {
101*94253393SJin Yao unsigned long value = strtol(s, &sep, 10);
102ffe0fb76SArnaldo Carvalho de Melo err = -EINVAL;
103ffe0fb76SArnaldo Carvalho de Melo if (*sep != ',' && *sep != '\0')
104ffe0fb76SArnaldo Carvalho de Melo break;
105ffe0fb76SArnaldo Carvalho de Melo err = intlist__add(ilist, value);
106ffe0fb76SArnaldo Carvalho de Melo if (err)
107ffe0fb76SArnaldo Carvalho de Melo break;
108ffe0fb76SArnaldo Carvalho de Melo s = sep + 1;
109ffe0fb76SArnaldo Carvalho de Melo } while (*sep != '\0');
110ffe0fb76SArnaldo Carvalho de Melo
111ffe0fb76SArnaldo Carvalho de Melo return err;
112ffe0fb76SArnaldo Carvalho de Melo }
113ffe0fb76SArnaldo Carvalho de Melo
intlist__new(const char * slist)114ffe0fb76SArnaldo Carvalho de Melo struct intlist *intlist__new(const char *slist)
11570b40c4aSDavid Ahern {
11670b40c4aSDavid Ahern struct intlist *ilist = malloc(sizeof(*ilist));
11770b40c4aSDavid Ahern
11870b40c4aSDavid Ahern if (ilist != NULL) {
11970b40c4aSDavid Ahern rblist__init(&ilist->rblist);
12070b40c4aSDavid Ahern ilist->rblist.node_cmp = intlist__node_cmp;
12170b40c4aSDavid Ahern ilist->rblist.node_new = intlist__node_new;
12270b40c4aSDavid Ahern ilist->rblist.node_delete = intlist__node_delete;
123ffe0fb76SArnaldo Carvalho de Melo
124ffe0fb76SArnaldo Carvalho de Melo if (slist && intlist__parse_list(ilist, slist))
125ffe0fb76SArnaldo Carvalho de Melo goto out_delete;
12670b40c4aSDavid Ahern }
12770b40c4aSDavid Ahern
12870b40c4aSDavid Ahern return ilist;
129ffe0fb76SArnaldo Carvalho de Melo out_delete:
130ffe0fb76SArnaldo Carvalho de Melo intlist__delete(ilist);
131ffe0fb76SArnaldo Carvalho de Melo return NULL;
13270b40c4aSDavid Ahern }
13370b40c4aSDavid Ahern
intlist__delete(struct intlist * ilist)13470b40c4aSDavid Ahern void intlist__delete(struct intlist *ilist)
13570b40c4aSDavid Ahern {
13670b40c4aSDavid Ahern if (ilist != NULL)
13770b40c4aSDavid Ahern rblist__delete(&ilist->rblist);
13870b40c4aSDavid Ahern }
13970b40c4aSDavid Ahern
intlist__entry(const struct intlist * ilist,unsigned int idx)14070b40c4aSDavid Ahern struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx)
14170b40c4aSDavid Ahern {
14270b40c4aSDavid Ahern struct int_node *node = NULL;
14370b40c4aSDavid Ahern struct rb_node *rb_node;
14470b40c4aSDavid Ahern
14570b40c4aSDavid Ahern rb_node = rblist__entry(&ilist->rblist, idx);
14670b40c4aSDavid Ahern if (rb_node)
14770b40c4aSDavid Ahern node = container_of(rb_node, struct int_node, rb_node);
14870b40c4aSDavid Ahern
14970b40c4aSDavid Ahern return node;
15070b40c4aSDavid Ahern }
151