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