xref: /aosp_15_r20/external/e2fsprogs/lib/ext2fs/rbtree.h (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker   Red Black Trees
3*6a54128fSAndroid Build Coastguard Worker   (C) 1999  Andrea Arcangeli <[email protected]>
4*6a54128fSAndroid Build Coastguard Worker 
5*6a54128fSAndroid Build Coastguard Worker   This program is free software; you can redistribute it and/or modify
6*6a54128fSAndroid Build Coastguard Worker   it under the terms of the GNU General Public License as published by
7*6a54128fSAndroid Build Coastguard Worker   the Free Software Foundation; either version 2 of the License, or
8*6a54128fSAndroid Build Coastguard Worker   (at your option) any later version.
9*6a54128fSAndroid Build Coastguard Worker 
10*6a54128fSAndroid Build Coastguard Worker   This program is distributed in the hope that it will be useful,
11*6a54128fSAndroid Build Coastguard Worker   but WITHOUT ANY WARRANTY; without even the implied warranty of
12*6a54128fSAndroid Build Coastguard Worker   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*6a54128fSAndroid Build Coastguard Worker   GNU General Public License for more details.
14*6a54128fSAndroid Build Coastguard Worker 
15*6a54128fSAndroid Build Coastguard Worker   You should have received a copy of the GNU General Public License
16*6a54128fSAndroid Build Coastguard Worker   along with this program; if not, write to the Free Software
17*6a54128fSAndroid Build Coastguard Worker   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18*6a54128fSAndroid Build Coastguard Worker 
19*6a54128fSAndroid Build Coastguard Worker   linux/include/linux/rbtree.h
20*6a54128fSAndroid Build Coastguard Worker 
21*6a54128fSAndroid Build Coastguard Worker   To use rbtrees you'll have to implement your own insert and search cores.
22*6a54128fSAndroid Build Coastguard Worker   This will avoid us to use callbacks and to drop dramatically performances.
23*6a54128fSAndroid Build Coastguard Worker   I know it's not the cleaner way,  but in C (not in C++) to get
24*6a54128fSAndroid Build Coastguard Worker   performances and genericity...
25*6a54128fSAndroid Build Coastguard Worker 
26*6a54128fSAndroid Build Coastguard Worker   Some example of insert and search follows here. The search is a plain
27*6a54128fSAndroid Build Coastguard Worker   normal search over an ordered tree. The insert instead must be implemented
28*6a54128fSAndroid Build Coastguard Worker   in two steps: First, the code must insert the element in order as a red leaf
29*6a54128fSAndroid Build Coastguard Worker   in the tree, and then the support library function rb_insert_color() must
30*6a54128fSAndroid Build Coastguard Worker   be called. Such function will do the not trivial work to rebalance the
31*6a54128fSAndroid Build Coastguard Worker   rbtree, if necessary.
32*6a54128fSAndroid Build Coastguard Worker 
33*6a54128fSAndroid Build Coastguard Worker -----------------------------------------------------------------------
34*6a54128fSAndroid Build Coastguard Worker static inline struct page * rb_search_page_cache(struct inode * inode,
35*6a54128fSAndroid Build Coastguard Worker 						 unsigned long offset)
36*6a54128fSAndroid Build Coastguard Worker {
37*6a54128fSAndroid Build Coastguard Worker 	struct rb_node * n = inode->i_rb_page_cache.rb_node;
38*6a54128fSAndroid Build Coastguard Worker 	struct page * page;
39*6a54128fSAndroid Build Coastguard Worker 
40*6a54128fSAndroid Build Coastguard Worker 	while (n)
41*6a54128fSAndroid Build Coastguard Worker 	{
42*6a54128fSAndroid Build Coastguard Worker 		page = rb_entry(n, struct page, rb_page_cache);
43*6a54128fSAndroid Build Coastguard Worker 
44*6a54128fSAndroid Build Coastguard Worker 		if (offset < page->offset)
45*6a54128fSAndroid Build Coastguard Worker 			n = n->rb_left;
46*6a54128fSAndroid Build Coastguard Worker 		else if (offset > page->offset)
47*6a54128fSAndroid Build Coastguard Worker 			n = n->rb_right;
48*6a54128fSAndroid Build Coastguard Worker 		else
49*6a54128fSAndroid Build Coastguard Worker 			return page;
50*6a54128fSAndroid Build Coastguard Worker 	}
51*6a54128fSAndroid Build Coastguard Worker 	return NULL;
52*6a54128fSAndroid Build Coastguard Worker }
53*6a54128fSAndroid Build Coastguard Worker 
54*6a54128fSAndroid Build Coastguard Worker static inline struct page * __rb_insert_page_cache(struct inode * inode,
55*6a54128fSAndroid Build Coastguard Worker 						   unsigned long offset,
56*6a54128fSAndroid Build Coastguard Worker 						   struct rb_node * node)
57*6a54128fSAndroid Build Coastguard Worker {
58*6a54128fSAndroid Build Coastguard Worker 	struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
59*6a54128fSAndroid Build Coastguard Worker 	struct rb_node * parent = NULL;
60*6a54128fSAndroid Build Coastguard Worker 	struct page * page;
61*6a54128fSAndroid Build Coastguard Worker 
62*6a54128fSAndroid Build Coastguard Worker 	while (*p)
63*6a54128fSAndroid Build Coastguard Worker 	{
64*6a54128fSAndroid Build Coastguard Worker 		parent = *p;
65*6a54128fSAndroid Build Coastguard Worker 		page = rb_entry(parent, struct page, rb_page_cache);
66*6a54128fSAndroid Build Coastguard Worker 
67*6a54128fSAndroid Build Coastguard Worker 		if (offset < page->offset)
68*6a54128fSAndroid Build Coastguard Worker 			p = &(*p)->rb_left;
69*6a54128fSAndroid Build Coastguard Worker 		else if (offset > page->offset)
70*6a54128fSAndroid Build Coastguard Worker 			p = &(*p)->rb_right;
71*6a54128fSAndroid Build Coastguard Worker 		else
72*6a54128fSAndroid Build Coastguard Worker 			return page;
73*6a54128fSAndroid Build Coastguard Worker 	}
74*6a54128fSAndroid Build Coastguard Worker 
75*6a54128fSAndroid Build Coastguard Worker 	rb_link_node(node, parent, p);
76*6a54128fSAndroid Build Coastguard Worker 
77*6a54128fSAndroid Build Coastguard Worker 	return NULL;
78*6a54128fSAndroid Build Coastguard Worker }
79*6a54128fSAndroid Build Coastguard Worker 
80*6a54128fSAndroid Build Coastguard Worker static inline struct page * rb_insert_page_cache(struct inode * inode,
81*6a54128fSAndroid Build Coastguard Worker 						 unsigned long offset,
82*6a54128fSAndroid Build Coastguard Worker 						 struct rb_node * node)
83*6a54128fSAndroid Build Coastguard Worker {
84*6a54128fSAndroid Build Coastguard Worker 	struct page * ret;
85*6a54128fSAndroid Build Coastguard Worker 	if ((ret = __rb_insert_page_cache(inode, offset, node)))
86*6a54128fSAndroid Build Coastguard Worker 		goto out;
87*6a54128fSAndroid Build Coastguard Worker 	rb_insert_color(node, &inode->i_rb_page_cache);
88*6a54128fSAndroid Build Coastguard Worker  out:
89*6a54128fSAndroid Build Coastguard Worker 	return ret;
90*6a54128fSAndroid Build Coastguard Worker }
91*6a54128fSAndroid Build Coastguard Worker -----------------------------------------------------------------------
92*6a54128fSAndroid Build Coastguard Worker */
93*6a54128fSAndroid Build Coastguard Worker 
94*6a54128fSAndroid Build Coastguard Worker #ifndef	_LINUX_RBTREE_H
95*6a54128fSAndroid Build Coastguard Worker #define	_LINUX_RBTREE_H
96*6a54128fSAndroid Build Coastguard Worker 
97*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
98*6a54128fSAndroid Build Coastguard Worker #include <stdint.h>
99*6a54128fSAndroid Build Coastguard Worker #include "compiler.h"
100*6a54128fSAndroid Build Coastguard Worker 
101*6a54128fSAndroid Build Coastguard Worker #if __GNUC_PREREQ (4, 6)
102*6a54128fSAndroid Build Coastguard Worker #pragma GCC diagnostic push
103*6a54128fSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wunused-function"
104*6a54128fSAndroid Build Coastguard Worker #endif
105*6a54128fSAndroid Build Coastguard Worker 
106*6a54128fSAndroid Build Coastguard Worker struct rb_node
107*6a54128fSAndroid Build Coastguard Worker {
108*6a54128fSAndroid Build Coastguard Worker 	uintptr_t  rb_parent_color;
109*6a54128fSAndroid Build Coastguard Worker #define	RB_RED		0
110*6a54128fSAndroid Build Coastguard Worker #define	RB_BLACK	1
111*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *rb_right;
112*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *rb_left;
113*6a54128fSAndroid Build Coastguard Worker } __attribute__((aligned(sizeof(long))));
114*6a54128fSAndroid Build Coastguard Worker     /* The alignment might seem pointless, but allegedly CRIS needs it */
115*6a54128fSAndroid Build Coastguard Worker 
116*6a54128fSAndroid Build Coastguard Worker struct rb_root
117*6a54128fSAndroid Build Coastguard Worker {
118*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *rb_node;
119*6a54128fSAndroid Build Coastguard Worker };
120*6a54128fSAndroid Build Coastguard Worker 
121*6a54128fSAndroid Build Coastguard Worker 
122*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
123*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_color(r)   ((r)->rb_parent_color & 1)
124*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_is_red(r)   (!ext2fs_rb_color(r))
125*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_is_black(r) ext2fs_rb_color(r)
126*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
127*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)
128*6a54128fSAndroid Build Coastguard Worker 
ext2fs_rb_set_parent(struct rb_node * rb,struct rb_node * p)129*6a54128fSAndroid Build Coastguard Worker static inline void ext2fs_rb_set_parent(struct rb_node *rb, struct rb_node *p)
130*6a54128fSAndroid Build Coastguard Worker {
131*6a54128fSAndroid Build Coastguard Worker 	rb->rb_parent_color = (rb->rb_parent_color & 3) | (uintptr_t)p;
132*6a54128fSAndroid Build Coastguard Worker }
ext2fs_rb_set_color(struct rb_node * rb,int color)133*6a54128fSAndroid Build Coastguard Worker static inline void ext2fs_rb_set_color(struct rb_node *rb, int color)
134*6a54128fSAndroid Build Coastguard Worker {
135*6a54128fSAndroid Build Coastguard Worker 	rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
136*6a54128fSAndroid Build Coastguard Worker }
137*6a54128fSAndroid Build Coastguard Worker 
138*6a54128fSAndroid Build Coastguard Worker #define RB_ROOT	(struct rb_root) { NULL, }
139*6a54128fSAndroid Build Coastguard Worker #define	ext2fs_rb_entry(ptr, type, member) container_of(ptr, type, member)
140*6a54128fSAndroid Build Coastguard Worker 
ext2fs_rb_empty_root(struct rb_root * root)141*6a54128fSAndroid Build Coastguard Worker static inline int ext2fs_rb_empty_root(struct rb_root *root)
142*6a54128fSAndroid Build Coastguard Worker {
143*6a54128fSAndroid Build Coastguard Worker 	return root->rb_node == NULL;
144*6a54128fSAndroid Build Coastguard Worker }
145*6a54128fSAndroid Build Coastguard Worker 
ext2fs_rb_empty_node(struct rb_node * node)146*6a54128fSAndroid Build Coastguard Worker static inline int ext2fs_rb_empty_node(struct rb_node *node)
147*6a54128fSAndroid Build Coastguard Worker {
148*6a54128fSAndroid Build Coastguard Worker 	return ext2fs_rb_parent(node) == node;
149*6a54128fSAndroid Build Coastguard Worker }
150*6a54128fSAndroid Build Coastguard Worker 
ext2fs_rb_clear_node(struct rb_node * node)151*6a54128fSAndroid Build Coastguard Worker static inline void ext2fs_rb_clear_node(struct rb_node *node)
152*6a54128fSAndroid Build Coastguard Worker {
153*6a54128fSAndroid Build Coastguard Worker 	ext2fs_rb_set_parent(node, node);
154*6a54128fSAndroid Build Coastguard Worker }
155*6a54128fSAndroid Build Coastguard Worker 
156*6a54128fSAndroid Build Coastguard Worker extern void ext2fs_rb_insert_color(struct rb_node *, struct rb_root *);
157*6a54128fSAndroid Build Coastguard Worker extern void ext2fs_rb_erase(struct rb_node *, struct rb_root *);
158*6a54128fSAndroid Build Coastguard Worker 
159*6a54128fSAndroid Build Coastguard Worker /* Find logical next and previous nodes in a tree */
160*6a54128fSAndroid Build Coastguard Worker extern struct rb_node *ext2fs_rb_next(struct rb_node *);
161*6a54128fSAndroid Build Coastguard Worker extern struct rb_node *ext2fs_rb_prev(struct rb_node *);
162*6a54128fSAndroid Build Coastguard Worker extern struct rb_node *ext2fs_rb_first(const struct rb_root *);
163*6a54128fSAndroid Build Coastguard Worker extern struct rb_node *ext2fs_rb_last(const struct rb_root *);
164*6a54128fSAndroid Build Coastguard Worker 
165*6a54128fSAndroid Build Coastguard Worker /* Fast replacement of a single node without remove/rebalance/add/rebalance */
166*6a54128fSAndroid Build Coastguard Worker extern void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new,
167*6a54128fSAndroid Build Coastguard Worker 				 struct rb_root *root);
168*6a54128fSAndroid Build Coastguard Worker 
ext2fs_rb_link_node(struct rb_node * node,struct rb_node * parent,struct rb_node ** rb_link)169*6a54128fSAndroid Build Coastguard Worker static inline void ext2fs_rb_link_node(struct rb_node * node,
170*6a54128fSAndroid Build Coastguard Worker 				     struct rb_node * parent,
171*6a54128fSAndroid Build Coastguard Worker 				     struct rb_node ** rb_link)
172*6a54128fSAndroid Build Coastguard Worker {
173*6a54128fSAndroid Build Coastguard Worker 	node->rb_parent_color = (uintptr_t)parent;
174*6a54128fSAndroid Build Coastguard Worker 	node->rb_left = node->rb_right = NULL;
175*6a54128fSAndroid Build Coastguard Worker 
176*6a54128fSAndroid Build Coastguard Worker 	*rb_link = node;
177*6a54128fSAndroid Build Coastguard Worker }
178*6a54128fSAndroid Build Coastguard Worker 
179*6a54128fSAndroid Build Coastguard Worker #if __GNUC_PREREQ (4, 6)
180*6a54128fSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
181*6a54128fSAndroid Build Coastguard Worker #endif
182*6a54128fSAndroid Build Coastguard Worker 
183*6a54128fSAndroid Build Coastguard Worker #endif	/* _LINUX_RBTREE_H */
184