xref: /OK3568_Linux_fs/kernel/tools/perf/util/rblist.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Based on strlist.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 <stdio.h>
9*4882a593Smuzhiyun #include <stdlib.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "rblist.h"
12*4882a593Smuzhiyun 
rblist__add_node(struct rblist * rblist,const void * new_entry)13*4882a593Smuzhiyun int rblist__add_node(struct rblist *rblist, const void *new_entry)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun 	struct rb_node **p = &rblist->entries.rb_root.rb_node;
16*4882a593Smuzhiyun 	struct rb_node *parent = NULL, *new_node;
17*4882a593Smuzhiyun 	bool leftmost = true;
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun 	while (*p != NULL) {
20*4882a593Smuzhiyun 		int rc;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun 		parent = *p;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 		rc = rblist->node_cmp(parent, new_entry);
25*4882a593Smuzhiyun 		if (rc > 0)
26*4882a593Smuzhiyun 			p = &(*p)->rb_left;
27*4882a593Smuzhiyun 		else if (rc < 0) {
28*4882a593Smuzhiyun 			p = &(*p)->rb_right;
29*4882a593Smuzhiyun 			leftmost = false;
30*4882a593Smuzhiyun 		}
31*4882a593Smuzhiyun 		else
32*4882a593Smuzhiyun 			return -EEXIST;
33*4882a593Smuzhiyun 	}
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	new_node = rblist->node_new(rblist, new_entry);
36*4882a593Smuzhiyun 	if (new_node == NULL)
37*4882a593Smuzhiyun 		return -ENOMEM;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	rb_link_node(new_node, parent, p);
40*4882a593Smuzhiyun 	rb_insert_color_cached(new_node, &rblist->entries, leftmost);
41*4882a593Smuzhiyun 	++rblist->nr_entries;
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	return 0;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
rblist__remove_node(struct rblist * rblist,struct rb_node * rb_node)46*4882a593Smuzhiyun void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	rb_erase_cached(rb_node, &rblist->entries);
49*4882a593Smuzhiyun 	--rblist->nr_entries;
50*4882a593Smuzhiyun 	rblist->node_delete(rblist, rb_node);
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
__rblist__findnew(struct rblist * rblist,const void * entry,bool create)53*4882a593Smuzhiyun static struct rb_node *__rblist__findnew(struct rblist *rblist,
54*4882a593Smuzhiyun 					 const void *entry,
55*4882a593Smuzhiyun 					 bool create)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	struct rb_node **p = &rblist->entries.rb_root.rb_node;
58*4882a593Smuzhiyun 	struct rb_node *parent = NULL, *new_node = NULL;
59*4882a593Smuzhiyun 	bool leftmost = true;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	while (*p != NULL) {
62*4882a593Smuzhiyun 		int rc;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 		parent = *p;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 		rc = rblist->node_cmp(parent, entry);
67*4882a593Smuzhiyun 		if (rc > 0)
68*4882a593Smuzhiyun 			p = &(*p)->rb_left;
69*4882a593Smuzhiyun 		else if (rc < 0) {
70*4882a593Smuzhiyun 			p = &(*p)->rb_right;
71*4882a593Smuzhiyun 			leftmost = false;
72*4882a593Smuzhiyun 		}
73*4882a593Smuzhiyun 		else
74*4882a593Smuzhiyun 			return parent;
75*4882a593Smuzhiyun 	}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	if (create) {
78*4882a593Smuzhiyun 		new_node = rblist->node_new(rblist, entry);
79*4882a593Smuzhiyun 		if (new_node) {
80*4882a593Smuzhiyun 			rb_link_node(new_node, parent, p);
81*4882a593Smuzhiyun 			rb_insert_color_cached(new_node,
82*4882a593Smuzhiyun 					       &rblist->entries, leftmost);
83*4882a593Smuzhiyun 			++rblist->nr_entries;
84*4882a593Smuzhiyun 		}
85*4882a593Smuzhiyun 	}
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return new_node;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
rblist__find(struct rblist * rblist,const void * entry)90*4882a593Smuzhiyun struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	return __rblist__findnew(rblist, entry, false);
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
rblist__findnew(struct rblist * rblist,const void * entry)95*4882a593Smuzhiyun struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun 	return __rblist__findnew(rblist, entry, true);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun 
rblist__init(struct rblist * rblist)100*4882a593Smuzhiyun void rblist__init(struct rblist *rblist)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	if (rblist != NULL) {
103*4882a593Smuzhiyun 		rblist->entries	 = RB_ROOT_CACHED;
104*4882a593Smuzhiyun 		rblist->nr_entries = 0;
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	return;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun 
rblist__exit(struct rblist * rblist)110*4882a593Smuzhiyun void rblist__exit(struct rblist *rblist)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	struct rb_node *pos, *next = rb_first_cached(&rblist->entries);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	while (next) {
115*4882a593Smuzhiyun 		pos = next;
116*4882a593Smuzhiyun 		next = rb_next(pos);
117*4882a593Smuzhiyun 		rblist__remove_node(rblist, pos);
118*4882a593Smuzhiyun 	}
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
rblist__delete(struct rblist * rblist)121*4882a593Smuzhiyun void rblist__delete(struct rblist *rblist)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	if (rblist != NULL) {
124*4882a593Smuzhiyun 		rblist__exit(rblist);
125*4882a593Smuzhiyun 		free(rblist);
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
rblist__entry(const struct rblist * rblist,unsigned int idx)129*4882a593Smuzhiyun struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	struct rb_node *node;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	for (node = rb_first_cached(&rblist->entries); node;
134*4882a593Smuzhiyun 	     node = rb_next(node)) {
135*4882a593Smuzhiyun 		if (!idx--)
136*4882a593Smuzhiyun 			return node;
137*4882a593Smuzhiyun 	}
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	return NULL;
140*4882a593Smuzhiyun }
141