xref: /openbmc/linux/tools/perf/util/intlist.c (revision d0034a7a4ac7fae708146ac0059b9c47a1543f0d)
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