File: | ctk/ctkrbtree.c |
Warning: | line 268, column 8 Access to field 'left' results in a dereference of a null pointer (loaded from variable 'w') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* ctkrbtree.c | |||
2 | * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com> | |||
3 | * | |||
4 | * This library is free software; you can redistribute it and/or | |||
5 | * modify it under the terms of the GNU Library General Public | |||
6 | * License as published by the Free Software Foundation; either | |||
7 | * version 2 of the License, or (at your option) any later version. | |||
8 | * | |||
9 | * This library is distributed in the hope that it will be useful, | |||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
12 | * Library General Public License for more details. | |||
13 | * | |||
14 | * You should have received a copy of the GNU Library General Public | |||
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | |||
16 | */ | |||
17 | ||||
18 | #include "config.h" | |||
19 | #include "ctkrbtree.h" | |||
20 | #include "ctkdebug.h" | |||
21 | ||||
22 | static CtkRBNode * _ctk_rbnode_new (CtkRBTree *tree, | |||
23 | gint height); | |||
24 | static void _ctk_rbnode_free (CtkRBNode *node); | |||
25 | static void _ctk_rbnode_rotate_left (CtkRBTree *tree, | |||
26 | CtkRBNode *node); | |||
27 | static void _ctk_rbnode_rotate_right (CtkRBTree *tree, | |||
28 | CtkRBNode *node); | |||
29 | static void _ctk_rbtree_insert_fixup (CtkRBTree *tree, | |||
30 | CtkRBNode *node); | |||
31 | static void _ctk_rbtree_remove_node_fixup (CtkRBTree *tree, | |||
32 | CtkRBNode *node, | |||
33 | CtkRBNode *parent); | |||
34 | static inline void _fixup_validation (CtkRBTree *tree, | |||
35 | CtkRBNode *node); | |||
36 | static inline void _fixup_total_count (CtkRBTree *tree, | |||
37 | CtkRBNode *node); | |||
38 | #ifdef G_ENABLE_DEBUG1 | |||
39 | static void _ctk_rbtree_test (const gchar *where, | |||
40 | CtkRBTree *tree); | |||
41 | static void _ctk_rbtree_debug_spew (CtkRBTree *tree, | |||
42 | GString *s); | |||
43 | #endif | |||
44 | ||||
45 | static const CtkRBNode nil = { | |||
46 | .flags = CTK_RBNODE_BLACK, | |||
47 | }; | |||
48 | ||||
49 | gboolean | |||
50 | _ctk_rbtree_is_nil (CtkRBNode *node) | |||
51 | { | |||
52 | return node == &nil; | |||
53 | } | |||
54 | ||||
55 | static CtkRBNode * | |||
56 | _ctk_rbnode_new (CtkRBTree *tree G_GNUC_UNUSED__attribute__ ((__unused__)), | |||
57 | gint height) | |||
58 | { | |||
59 | CtkRBNode *node = g_slice_new (CtkRBNode)((CtkRBNode*) g_slice_alloc (sizeof (CtkRBNode))); | |||
60 | ||||
61 | node->left = (CtkRBNode *) &nil; | |||
62 | node->right = (CtkRBNode *) &nil; | |||
63 | node->parent = (CtkRBNode *) &nil; | |||
64 | node->flags = CTK_RBNODE_RED; | |||
65 | node->total_count = 1; | |||
66 | node->count = 1; | |||
67 | node->children = NULL((void*)0); | |||
68 | node->offset = height; | |||
69 | return node; | |||
70 | } | |||
71 | ||||
72 | static void | |||
73 | _ctk_rbnode_free (CtkRBNode *node) | |||
74 | { | |||
75 | #ifdef G_ENABLE_DEBUG1 | |||
76 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
77 | { | |||
78 | node->left = (gpointer) 0xdeadbeef; | |||
79 | node->right = (gpointer) 0xdeadbeef; | |||
80 | node->parent = (gpointer) 0xdeadbeef; | |||
81 | node->total_count = 56789; | |||
82 | node->offset = 56789; | |||
83 | node->count = 56789; | |||
84 | node->flags = 0; | |||
85 | } | |||
86 | #endif | |||
87 | g_slice_free (CtkRBNode, node)do { if (1) g_slice_free1 (sizeof (CtkRBNode), (node)); else ( void) ((CtkRBNode*) 0 == (node)); } while (0); | |||
88 | } | |||
89 | ||||
90 | static void | |||
91 | _ctk_rbnode_rotate_left (CtkRBTree *tree, | |||
92 | CtkRBNode *node) | |||
93 | { | |||
94 | gint node_height, right_height; | |||
95 | CtkRBNode *right; | |||
96 | ||||
97 | g_return_if_fail (!_ctk_rbtree_is_nil (node))do { if ((!_ctk_rbtree_is_nil (node))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "!_ctk_rbtree_is_nil (node)" ); return; } } while (0); | |||
98 | g_return_if_fail (!_ctk_rbtree_is_nil (node->right))do { if ((!_ctk_rbtree_is_nil (node->right))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "!_ctk_rbtree_is_nil (node->right)" ); return; } } while (0); | |||
99 | ||||
100 | right = node->right; | |||
101 | ||||
102 | node_height = CTK_RBNODE_GET_HEIGHT (node)(node->offset-(node->left->offset+node->right-> offset+(node->children?node->children->root->offset :0))); | |||
103 | right_height = CTK_RBNODE_GET_HEIGHT (right)(right->offset-(right->left->offset+right->right-> offset+(right->children?right->children->root->offset :0))); | |||
104 | node->right = right->left; | |||
105 | if (!_ctk_rbtree_is_nil (right->left)) | |||
106 | right->left->parent = node; | |||
107 | ||||
108 | right->parent = node->parent; | |||
109 | if (!_ctk_rbtree_is_nil (node->parent)) | |||
110 | { | |||
111 | if (node == node->parent->left) | |||
112 | node->parent->left = right; | |||
113 | else | |||
114 | node->parent->right = right; | |||
115 | } else { | |||
116 | tree->root = right; | |||
117 | } | |||
118 | ||||
119 | right->left = node; | |||
120 | node->parent = right; | |||
121 | ||||
122 | node->count = 1 + node->left->count + node->right->count; | |||
123 | right->count = 1 + right->left->count + right->right->count; | |||
124 | ||||
125 | node->offset = node_height + node->left->offset + node->right->offset + | |||
126 | (node->children ? node->children->root->offset : 0); | |||
127 | right->offset = right_height + right->left->offset + right->right->offset + | |||
128 | (right->children ? right->children->root->offset : 0); | |||
129 | ||||
130 | _fixup_validation (tree, node); | |||
131 | _fixup_validation (tree, right); | |||
132 | _fixup_total_count (tree, node); | |||
133 | _fixup_total_count (tree, right); | |||
134 | } | |||
135 | ||||
136 | static void | |||
137 | _ctk_rbnode_rotate_right (CtkRBTree *tree, | |||
138 | CtkRBNode *node) | |||
139 | { | |||
140 | gint node_height, left_height; | |||
141 | CtkRBNode *left; | |||
142 | ||||
143 | g_return_if_fail (!_ctk_rbtree_is_nil (node))do { if ((!_ctk_rbtree_is_nil (node))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "!_ctk_rbtree_is_nil (node)" ); return; } } while (0); | |||
144 | g_return_if_fail (!_ctk_rbtree_is_nil (node->left))do { if ((!_ctk_rbtree_is_nil (node->left))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "!_ctk_rbtree_is_nil (node->left)" ); return; } } while (0); | |||
145 | ||||
146 | left = node->left; | |||
147 | ||||
148 | node_height = CTK_RBNODE_GET_HEIGHT (node)(node->offset-(node->left->offset+node->right-> offset+(node->children?node->children->root->offset :0))); | |||
149 | left_height = CTK_RBNODE_GET_HEIGHT (left)(left->offset-(left->left->offset+left->right-> offset+(left->children?left->children->root->offset :0))); | |||
150 | ||||
151 | node->left = left->right; | |||
152 | if (!_ctk_rbtree_is_nil (left->right)) | |||
153 | left->right->parent = node; | |||
154 | ||||
155 | left->parent = node->parent; | |||
156 | if (!_ctk_rbtree_is_nil (node->parent)) | |||
157 | { | |||
158 | if (node == node->parent->right) | |||
159 | node->parent->right = left; | |||
160 | else | |||
161 | node->parent->left = left; | |||
162 | } | |||
163 | else | |||
164 | { | |||
165 | tree->root = left; | |||
166 | } | |||
167 | ||||
168 | /* link node and left */ | |||
169 | left->right = node; | |||
170 | node->parent = left; | |||
171 | ||||
172 | node->count = 1 + node->left->count + node->right->count; | |||
173 | left->count = 1 + left->left->count + left->right->count; | |||
174 | ||||
175 | node->offset = node_height + node->left->offset + node->right->offset + | |||
176 | (node->children ? node->children->root->offset : 0); | |||
177 | left->offset = left_height + left->left->offset + left->right->offset + | |||
178 | (left->children?left->children->root->offset:0); | |||
179 | ||||
180 | _fixup_validation (tree, node); | |||
181 | _fixup_validation (tree, left); | |||
182 | _fixup_total_count (tree, node); | |||
183 | _fixup_total_count (tree, left); | |||
184 | } | |||
185 | ||||
186 | static void | |||
187 | _ctk_rbtree_insert_fixup (CtkRBTree *tree, | |||
188 | CtkRBNode *node) | |||
189 | { | |||
190 | ||||
191 | /* check Red-Black properties */ | |||
192 | while (node != tree->root && CTK_RBNODE_GET_COLOR (node->parent)(node->parent?(((node->parent->flags&CTK_RBNODE_RED )==CTK_RBNODE_RED)?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK ) == CTK_RBNODE_RED) | |||
193 | { | |||
194 | /* we have a violation */ | |||
195 | if (node->parent == node->parent->parent->left) | |||
196 | { | |||
197 | CtkRBNode *y = node->parent->parent->right; | |||
198 | if (CTK_RBNODE_GET_COLOR (y)(y?(((y->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)?CTK_RBNODE_RED :CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_RED) | |||
199 | { | |||
200 | /* uncle is CTK_RBNODE_RED */ | |||
201 | CTK_RBNODE_SET_COLOR (node->parent, CTK_RBNODE_BLACK)if((node->parent->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK )node->parent->flags=node->parent->flags^(CTK_RBNODE_RED |CTK_RBNODE_BLACK); | |||
202 | CTK_RBNODE_SET_COLOR (y, CTK_RBNODE_BLACK)if((y->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK)y-> flags=y->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
203 | CTK_RBNODE_SET_COLOR (node->parent->parent, CTK_RBNODE_RED)if((node->parent->parent->flags&CTK_RBNODE_RED)!= CTK_RBNODE_RED)node->parent->parent->flags=node-> parent->parent->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
204 | node = node->parent->parent; | |||
205 | } | |||
206 | else | |||
207 | { | |||
208 | /* uncle is CTK_RBNODE_BLACK */ | |||
209 | if (node == node->parent->right) | |||
210 | { | |||
211 | /* make node a left child */ | |||
212 | node = node->parent; | |||
213 | _ctk_rbnode_rotate_left (tree, node); | |||
214 | } | |||
215 | ||||
216 | /* recolor and rotate */ | |||
217 | CTK_RBNODE_SET_COLOR (node->parent, CTK_RBNODE_BLACK)if((node->parent->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK )node->parent->flags=node->parent->flags^(CTK_RBNODE_RED |CTK_RBNODE_BLACK); | |||
218 | CTK_RBNODE_SET_COLOR (node->parent->parent, CTK_RBNODE_RED)if((node->parent->parent->flags&CTK_RBNODE_RED)!= CTK_RBNODE_RED)node->parent->parent->flags=node-> parent->parent->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
219 | _ctk_rbnode_rotate_right(tree, node->parent->parent); | |||
220 | } | |||
221 | } | |||
222 | else | |||
223 | { | |||
224 | /* mirror image of above code */ | |||
225 | CtkRBNode *y = node->parent->parent->left; | |||
226 | if (CTK_RBNODE_GET_COLOR (y)(y?(((y->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)?CTK_RBNODE_RED :CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_RED) | |||
227 | { | |||
228 | /* uncle is CTK_RBNODE_RED */ | |||
229 | CTK_RBNODE_SET_COLOR (node->parent, CTK_RBNODE_BLACK)if((node->parent->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK )node->parent->flags=node->parent->flags^(CTK_RBNODE_RED |CTK_RBNODE_BLACK); | |||
230 | CTK_RBNODE_SET_COLOR (y, CTK_RBNODE_BLACK)if((y->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK)y-> flags=y->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
231 | CTK_RBNODE_SET_COLOR (node->parent->parent, CTK_RBNODE_RED)if((node->parent->parent->flags&CTK_RBNODE_RED)!= CTK_RBNODE_RED)node->parent->parent->flags=node-> parent->parent->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
232 | node = node->parent->parent; | |||
233 | } | |||
234 | else | |||
235 | { | |||
236 | /* uncle is CTK_RBNODE_BLACK */ | |||
237 | if (node == node->parent->left) | |||
238 | { | |||
239 | node = node->parent; | |||
240 | _ctk_rbnode_rotate_right (tree, node); | |||
241 | } | |||
242 | CTK_RBNODE_SET_COLOR (node->parent, CTK_RBNODE_BLACK)if((node->parent->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK )node->parent->flags=node->parent->flags^(CTK_RBNODE_RED |CTK_RBNODE_BLACK); | |||
243 | CTK_RBNODE_SET_COLOR (node->parent->parent, CTK_RBNODE_RED)if((node->parent->parent->flags&CTK_RBNODE_RED)!= CTK_RBNODE_RED)node->parent->parent->flags=node-> parent->parent->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
244 | _ctk_rbnode_rotate_left (tree, node->parent->parent); | |||
245 | } | |||
246 | } | |||
247 | } | |||
248 | CTK_RBNODE_SET_COLOR (tree->root, CTK_RBNODE_BLACK)if((tree->root->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK )tree->root->flags=tree->root->flags^(CTK_RBNODE_RED |CTK_RBNODE_BLACK); | |||
249 | } | |||
250 | ||||
251 | static void | |||
252 | _ctk_rbtree_remove_node_fixup (CtkRBTree *tree, | |||
253 | CtkRBNode *node, | |||
254 | CtkRBNode *parent) | |||
255 | { | |||
256 | while (node != tree->root && CTK_RBNODE_GET_COLOR (node)(node?(((node->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)? CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_BLACK) | |||
| ||||
257 | { | |||
258 | if (node == parent->left) | |||
259 | { | |||
260 | CtkRBNode *w = parent->right; | |||
261 | if (CTK_RBNODE_GET_COLOR (w)(w?(((w->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)?CTK_RBNODE_RED :CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_RED) | |||
262 | { | |||
263 | CTK_RBNODE_SET_COLOR (w, CTK_RBNODE_BLACK)if((w->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK)w-> flags=w->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
264 | CTK_RBNODE_SET_COLOR (parent, CTK_RBNODE_RED)if((parent->flags&CTK_RBNODE_RED)!=CTK_RBNODE_RED)parent ->flags=parent->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
265 | _ctk_rbnode_rotate_left (tree, parent); | |||
266 | w = parent->right; | |||
267 | } | |||
268 | if (CTK_RBNODE_GET_COLOR (w->left)(w->left?(((w->left->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED )?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_BLACK && CTK_RBNODE_GET_COLOR (w->right)(w->right?(((w->right->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED )?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_BLACK) | |||
| ||||
269 | { | |||
270 | CTK_RBNODE_SET_COLOR (w, CTK_RBNODE_RED)if((w->flags&CTK_RBNODE_RED)!=CTK_RBNODE_RED)w->flags =w->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
271 | node = parent; | |||
272 | } | |||
273 | else | |||
274 | { | |||
275 | if (CTK_RBNODE_GET_COLOR (w->right)(w->right?(((w->right->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED )?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_BLACK) | |||
276 | { | |||
277 | CTK_RBNODE_SET_COLOR (w->left, CTK_RBNODE_BLACK)if((w->left->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK )w->left->flags=w->left->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK ); | |||
278 | CTK_RBNODE_SET_COLOR (w, CTK_RBNODE_RED)if((w->flags&CTK_RBNODE_RED)!=CTK_RBNODE_RED)w->flags =w->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
279 | _ctk_rbnode_rotate_right (tree, w); | |||
280 | w = parent->right; | |||
281 | } | |||
282 | CTK_RBNODE_SET_COLOR (w, CTK_RBNODE_GET_COLOR (parent))if((w->flags&(parent?(((parent->flags&CTK_RBNODE_RED )==CTK_RBNODE_RED)?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK ))!=(parent?(((parent->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED )?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK))w->flags =w->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
283 | CTK_RBNODE_SET_COLOR (parent, CTK_RBNODE_BLACK)if((parent->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK) parent->flags=parent->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK ); | |||
284 | CTK_RBNODE_SET_COLOR (w->right, CTK_RBNODE_BLACK)if((w->right->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK )w->right->flags=w->right->flags^(CTK_RBNODE_RED| CTK_RBNODE_BLACK); | |||
285 | _ctk_rbnode_rotate_left (tree, parent); | |||
286 | node = tree->root; | |||
287 | } | |||
288 | } | |||
289 | else | |||
290 | { | |||
291 | CtkRBNode *w = parent->left; | |||
292 | if (CTK_RBNODE_GET_COLOR (w)(w?(((w->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)?CTK_RBNODE_RED :CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_RED) | |||
293 | { | |||
294 | CTK_RBNODE_SET_COLOR (w, CTK_RBNODE_BLACK)if((w->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK)w-> flags=w->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
295 | CTK_RBNODE_SET_COLOR (parent, CTK_RBNODE_RED)if((parent->flags&CTK_RBNODE_RED)!=CTK_RBNODE_RED)parent ->flags=parent->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
296 | _ctk_rbnode_rotate_right (tree, parent); | |||
297 | w = parent->left; | |||
298 | } | |||
299 | if (CTK_RBNODE_GET_COLOR (w->right)(w->right?(((w->right->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED )?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_BLACK && CTK_RBNODE_GET_COLOR (w->left)(w->left?(((w->left->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED )?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_BLACK) | |||
300 | { | |||
301 | CTK_RBNODE_SET_COLOR (w, CTK_RBNODE_RED)if((w->flags&CTK_RBNODE_RED)!=CTK_RBNODE_RED)w->flags =w->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
302 | node = parent; | |||
303 | } | |||
304 | else | |||
305 | { | |||
306 | if (CTK_RBNODE_GET_COLOR (w->left)(w->left?(((w->left->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED )?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_BLACK) | |||
307 | { | |||
308 | CTK_RBNODE_SET_COLOR (w->right, CTK_RBNODE_BLACK)if((w->right->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK )w->right->flags=w->right->flags^(CTK_RBNODE_RED| CTK_RBNODE_BLACK); | |||
309 | CTK_RBNODE_SET_COLOR (w, CTK_RBNODE_RED)if((w->flags&CTK_RBNODE_RED)!=CTK_RBNODE_RED)w->flags =w->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
310 | _ctk_rbnode_rotate_left (tree, w); | |||
311 | w = parent->left; | |||
312 | } | |||
313 | CTK_RBNODE_SET_COLOR (w, CTK_RBNODE_GET_COLOR (parent))if((w->flags&(parent?(((parent->flags&CTK_RBNODE_RED )==CTK_RBNODE_RED)?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK ))!=(parent?(((parent->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED )?CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK))w->flags =w->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
314 | CTK_RBNODE_SET_COLOR (parent, CTK_RBNODE_BLACK)if((parent->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK) parent->flags=parent->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK ); | |||
315 | CTK_RBNODE_SET_COLOR (w->left, CTK_RBNODE_BLACK)if((w->left->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK )w->left->flags=w->left->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK ); | |||
316 | _ctk_rbnode_rotate_right (tree, parent); | |||
317 | node = tree->root; | |||
318 | } | |||
319 | } | |||
320 | ||||
321 | parent = node->parent; | |||
322 | } | |||
323 | CTK_RBNODE_SET_COLOR (node, CTK_RBNODE_BLACK)if((node->flags&CTK_RBNODE_BLACK)!=CTK_RBNODE_BLACK)node ->flags=node->flags^(CTK_RBNODE_RED|CTK_RBNODE_BLACK); | |||
324 | } | |||
325 | ||||
326 | CtkRBTree * | |||
327 | _ctk_rbtree_new (void) | |||
328 | { | |||
329 | CtkRBTree *retval; | |||
330 | ||||
331 | retval = g_new (CtkRBTree, 1)((CtkRBTree *) g_malloc_n ((1), sizeof (CtkRBTree))); | |||
332 | retval->parent_tree = NULL((void*)0); | |||
333 | retval->parent_node = NULL((void*)0); | |||
334 | ||||
335 | retval->root = (CtkRBNode *) &nil; | |||
336 | ||||
337 | return retval; | |||
338 | } | |||
339 | ||||
340 | static void | |||
341 | _ctk_rbtree_free_helper (CtkRBTree *tree G_GNUC_UNUSED__attribute__ ((__unused__)), | |||
342 | CtkRBNode *node, | |||
343 | gpointer data G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
344 | { | |||
345 | if (node->children) | |||
346 | _ctk_rbtree_free (node->children); | |||
347 | ||||
348 | _ctk_rbnode_free (node); | |||
349 | } | |||
350 | ||||
351 | void | |||
352 | _ctk_rbtree_free (CtkRBTree *tree) | |||
353 | { | |||
354 | _ctk_rbtree_traverse (tree, | |||
355 | tree->root, | |||
356 | G_POST_ORDER, | |||
357 | _ctk_rbtree_free_helper, | |||
358 | NULL((void*)0)); | |||
359 | ||||
360 | if (tree->parent_node && | |||
361 | tree->parent_node->children == tree) | |||
362 | tree->parent_node->children = NULL((void*)0); | |||
363 | g_free (tree); | |||
364 | } | |||
365 | ||||
366 | static void | |||
367 | ctk_rbnode_adjust (CtkRBTree *tree, | |||
368 | CtkRBNode *node, | |||
369 | int count_diff, | |||
370 | int total_count_diff, | |||
371 | int offset_diff) | |||
372 | { | |||
373 | while (tree && node && !_ctk_rbtree_is_nil (node)) | |||
374 | { | |||
375 | _fixup_validation (tree, node); | |||
376 | node->offset += offset_diff; | |||
377 | node->count += count_diff; | |||
378 | node->total_count += total_count_diff; | |||
379 | ||||
380 | node = node->parent; | |||
381 | if (_ctk_rbtree_is_nil (node)) | |||
382 | { | |||
383 | node = tree->parent_node; | |||
384 | tree = tree->parent_tree; | |||
385 | count_diff = 0; | |||
386 | } | |||
387 | } | |||
388 | } | |||
389 | ||||
390 | void | |||
391 | _ctk_rbtree_remove (CtkRBTree *tree) | |||
392 | { | |||
393 | #ifdef G_ENABLE_DEBUG1 | |||
394 | CtkRBTree *tmp_tree; | |||
395 | ||||
396 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
397 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "397", tree); | |||
398 | #endif | |||
399 | ||||
400 | /* ugly hack to make _fixup_validation work in the first iteration of the | |||
401 | * loop below */ | |||
402 | CTK_RBNODE_UNSET_FLAG (tree->root, CTK_RBNODE_DESCENDANTS_INVALID)do{ (tree->root->flags&=~(CTK_RBNODE_DESCENDANTS_INVALID )); }while (0); | |||
403 | ||||
404 | ctk_rbnode_adjust (tree->parent_tree, | |||
405 | tree->parent_node, | |||
406 | 0, | |||
407 | - (int) tree->root->total_count, | |||
408 | - tree->root->offset); | |||
409 | ||||
410 | #ifdef G_ENABLE_DEBUG1 | |||
411 | tmp_tree = tree->parent_tree; | |||
412 | #endif | |||
413 | ||||
414 | _ctk_rbtree_free (tree); | |||
415 | ||||
416 | #ifdef G_ENABLE_DEBUG1 | |||
417 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
418 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "418", tmp_tree); | |||
419 | #endif | |||
420 | } | |||
421 | ||||
422 | ||||
423 | CtkRBNode * | |||
424 | _ctk_rbtree_insert_after (CtkRBTree *tree, | |||
425 | CtkRBNode *current, | |||
426 | gint height, | |||
427 | gboolean valid) | |||
428 | { | |||
429 | CtkRBNode *node; | |||
430 | gboolean right = TRUE(!(0)); | |||
431 | ||||
432 | #ifdef G_ENABLE_DEBUG1 | |||
433 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
434 | { | |||
435 | GString *s; | |||
436 | ||||
437 | s = g_string_new (""); | |||
438 | g_string_append_printf (s, "_ctk_rbtree_insert_after: %p\n", current); | |||
439 | _ctk_rbtree_debug_spew (tree, s); | |||
440 | g_message ("%s", s->str); | |||
441 | g_string_free (s, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); | |||
442 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "442", tree); | |||
443 | } | |||
444 | #endif | |||
445 | ||||
446 | if (current != NULL((void*)0) && !_ctk_rbtree_is_nil (current->right)) | |||
447 | { | |||
448 | current = current->right; | |||
449 | while (!_ctk_rbtree_is_nil (current->left)) | |||
450 | current = current->left; | |||
451 | right = FALSE(0); | |||
452 | } | |||
453 | /* setup new node */ | |||
454 | node = _ctk_rbnode_new (tree, height); | |||
455 | ||||
456 | /* insert node in tree */ | |||
457 | if (current) | |||
458 | { | |||
459 | node->parent = current; | |||
460 | if (right) | |||
461 | current->right = node; | |||
462 | else | |||
463 | current->left = node; | |||
464 | ctk_rbnode_adjust (tree, node->parent, | |||
465 | 1, 1, height); | |||
466 | } | |||
467 | else | |||
468 | { | |||
469 | g_assert (_ctk_rbtree_is_nil (tree->root))do { if (_ctk_rbtree_is_nil (tree->root)) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 469, ((const char*) (__func__)), "_ctk_rbtree_is_nil (tree->root)" ); } while (0); | |||
470 | tree->root = node; | |||
471 | ctk_rbnode_adjust (tree->parent_tree, tree->parent_node, | |||
472 | 0, 1, height); | |||
473 | } | |||
474 | ||||
475 | if (valid) | |||
476 | _ctk_rbtree_node_mark_valid (tree, node); | |||
477 | else | |||
478 | _ctk_rbtree_node_mark_invalid (tree, node); | |||
479 | ||||
480 | _ctk_rbtree_insert_fixup (tree, node); | |||
481 | ||||
482 | #ifdef G_ENABLE_DEBUG1 | |||
483 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
484 | { | |||
485 | GString *s; | |||
486 | ||||
487 | s = g_string_new ("_ctk_rbtree_insert_after finished...\n"); | |||
488 | _ctk_rbtree_debug_spew (tree, s); | |||
489 | g_message ("%s", s->str); | |||
490 | g_string_free (s, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); | |||
491 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "491", tree); | |||
492 | } | |||
493 | #endif | |||
494 | ||||
495 | return node; | |||
496 | } | |||
497 | ||||
498 | CtkRBNode * | |||
499 | _ctk_rbtree_insert_before (CtkRBTree *tree, | |||
500 | CtkRBNode *current, | |||
501 | gint height, | |||
502 | gboolean valid) | |||
503 | { | |||
504 | CtkRBNode *node; | |||
505 | gboolean left = TRUE(!(0)); | |||
506 | ||||
507 | #ifdef G_ENABLE_DEBUG1 | |||
508 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
509 | { | |||
510 | GString *s; | |||
511 | ||||
512 | s = g_string_new (""); | |||
513 | g_string_append_printf (s, "_ctk_rbtree_insert_before: %p\n", current); | |||
514 | _ctk_rbtree_debug_spew (tree, s); | |||
515 | g_message ("%s", s->str); | |||
516 | g_string_free (s, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); | |||
517 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "517", tree); | |||
518 | } | |||
519 | #endif | |||
520 | ||||
521 | if (current != NULL((void*)0) && !_ctk_rbtree_is_nil (current->left)) | |||
522 | { | |||
523 | current = current->left; | |||
524 | while (!_ctk_rbtree_is_nil (current->right)) | |||
525 | current = current->right; | |||
526 | left = FALSE(0); | |||
527 | } | |||
528 | ||||
529 | /* setup new node */ | |||
530 | node = _ctk_rbnode_new (tree, height); | |||
531 | ||||
532 | /* insert node in tree */ | |||
533 | if (current) | |||
534 | { | |||
535 | node->parent = current; | |||
536 | if (left) | |||
537 | current->left = node; | |||
538 | else | |||
539 | current->right = node; | |||
540 | ctk_rbnode_adjust (tree, node->parent, | |||
541 | 1, 1, height); | |||
542 | } | |||
543 | else | |||
544 | { | |||
545 | g_assert (_ctk_rbtree_is_nil (tree->root))do { if (_ctk_rbtree_is_nil (tree->root)) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 545, ((const char*) (__func__)), "_ctk_rbtree_is_nil (tree->root)" ); } while (0); | |||
546 | tree->root = node; | |||
547 | ctk_rbnode_adjust (tree->parent_tree, tree->parent_node, | |||
548 | 0, 1, height); | |||
549 | } | |||
550 | ||||
551 | if (valid) | |||
552 | _ctk_rbtree_node_mark_valid (tree, node); | |||
553 | else | |||
554 | _ctk_rbtree_node_mark_invalid (tree, node); | |||
555 | ||||
556 | _ctk_rbtree_insert_fixup (tree, node); | |||
557 | ||||
558 | #ifdef G_ENABLE_DEBUG1 | |||
559 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
560 | { | |||
561 | GString *s; | |||
562 | ||||
563 | s = g_string_new ("_ctk_rbtree_insert_before finished...\n"); | |||
564 | _ctk_rbtree_debug_spew (tree, s); | |||
565 | g_message ("%s", s->str); | |||
566 | g_string_free (s, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); | |||
567 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "567", tree); | |||
568 | } | |||
569 | #endif | |||
570 | ||||
571 | return node; | |||
572 | } | |||
573 | ||||
574 | CtkRBNode * | |||
575 | _ctk_rbtree_find_count (CtkRBTree *tree, | |||
576 | gint count) | |||
577 | { | |||
578 | CtkRBNode *node; | |||
579 | ||||
580 | node = tree->root; | |||
581 | while (!_ctk_rbtree_is_nil (node) && (node->left->count + 1 != count)) | |||
582 | { | |||
583 | if (node->left->count >= count) | |||
584 | node = node->left; | |||
585 | else | |||
586 | { | |||
587 | count -= (node->left->count + 1); | |||
588 | node = node->right; | |||
589 | } | |||
590 | } | |||
591 | if (_ctk_rbtree_is_nil (node)) | |||
592 | return NULL((void*)0); | |||
593 | return node; | |||
594 | } | |||
595 | ||||
596 | void | |||
597 | _ctk_rbtree_node_set_height (CtkRBTree *tree, | |||
598 | CtkRBNode *node, | |||
599 | gint height) | |||
600 | { | |||
601 | gint diff = height - CTK_RBNODE_GET_HEIGHT (node)(node->offset-(node->left->offset+node->right-> offset+(node->children?node->children->root->offset :0))); | |||
602 | ||||
603 | if (diff == 0) | |||
604 | return; | |||
605 | ||||
606 | ctk_rbnode_adjust (tree, node, 0, 0, diff); | |||
607 | ||||
608 | #ifdef G_ENABLE_DEBUG1 | |||
609 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
610 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "610", tree); | |||
611 | #endif | |||
612 | } | |||
613 | ||||
614 | void | |||
615 | _ctk_rbtree_node_mark_invalid (CtkRBTree *tree, | |||
616 | CtkRBNode *node) | |||
617 | { | |||
618 | if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID )?(!(0)):(0)):(0))) | |||
619 | return; | |||
620 | ||||
621 | CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_INVALID)do{ (node->flags|=CTK_RBNODE_INVALID); }while (0); | |||
622 | do | |||
623 | { | |||
624 | if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_DESCENDANTS_INVALID)(node?(((node->flags&CTK_RBNODE_DESCENDANTS_INVALID)== CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))) | |||
625 | return; | |||
626 | CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_DESCENDANTS_INVALID)do{ (node->flags|=CTK_RBNODE_DESCENDANTS_INVALID); }while ( 0); | |||
627 | node = node->parent; | |||
628 | if (_ctk_rbtree_is_nil (node)) | |||
629 | { | |||
630 | node = tree->parent_node; | |||
631 | tree = tree->parent_tree; | |||
632 | } | |||
633 | } | |||
634 | while (node); | |||
635 | } | |||
636 | ||||
637 | #if 0 | |||
638 | /* Draconian version. */ | |||
639 | void | |||
640 | _ctk_rbtree_node_mark_invalid (CtkRBTree *tree, | |||
641 | CtkRBNode *node) | |||
642 | { | |||
643 | CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_INVALID)do{ (node->flags|=CTK_RBNODE_INVALID); }while (0); | |||
644 | do | |||
645 | { | |||
646 | _fixup_validation (tree, node); | |||
647 | node = node->parent; | |||
648 | if (_ctk_rbtree_is_nil (node)) | |||
649 | { | |||
650 | node = tree->parent_node; | |||
651 | tree = tree->parent_tree; | |||
652 | } | |||
653 | } | |||
654 | while (node); | |||
655 | } | |||
656 | #endif | |||
657 | ||||
658 | void | |||
659 | _ctk_rbtree_node_mark_valid (CtkRBTree *tree, | |||
660 | CtkRBNode *node) | |||
661 | { | |||
662 | if ((!CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID )?(!(0)):(0)):(0))) && | |||
663 | (!CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID )?(!(0)):(0)):(0)))) | |||
664 | return; | |||
665 | ||||
666 | CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_INVALID)do{ (node->flags&=~(CTK_RBNODE_INVALID)); }while (0); | |||
667 | CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_COLUMN_INVALID)do{ (node->flags&=~(CTK_RBNODE_COLUMN_INVALID)); }while (0); | |||
668 | ||||
669 | do | |||
670 | { | |||
671 | if ((CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID )?(!(0)):(0)):(0))) || | |||
672 | (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID )?(!(0)):(0)):(0))) || | |||
673 | (node->children && CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID)(node->children->root?(((node->children->root-> flags&CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0))) || | |||
674 | (CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID)(node->left?(((node->left->flags&CTK_RBNODE_DESCENDANTS_INVALID )==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))) || | |||
675 | (CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID)(node->right?(((node->right->flags&CTK_RBNODE_DESCENDANTS_INVALID )==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0)))) | |||
676 | return; | |||
677 | ||||
678 | CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_DESCENDANTS_INVALID)do{ (node->flags&=~(CTK_RBNODE_DESCENDANTS_INVALID)); } while (0); | |||
679 | node = node->parent; | |||
680 | if (_ctk_rbtree_is_nil (node)) | |||
681 | { | |||
682 | node = tree->parent_node; | |||
683 | tree = tree->parent_tree; | |||
684 | } | |||
685 | } | |||
686 | while (node); | |||
687 | } | |||
688 | ||||
689 | #if 0 | |||
690 | /* Draconian version */ | |||
691 | void | |||
692 | _ctk_rbtree_node_mark_valid (CtkRBTree *tree, | |||
693 | CtkRBNode *node) | |||
694 | { | |||
695 | CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_INVALID)do{ (node->flags&=~(CTK_RBNODE_INVALID)); }while (0); | |||
696 | CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_COLUMN_INVALID)do{ (node->flags&=~(CTK_RBNODE_COLUMN_INVALID)); }while (0); | |||
697 | ||||
698 | do | |||
699 | { | |||
700 | _fixup_validation (tree, node); | |||
701 | node = node->parent; | |||
702 | if (_ctk_rbtree_is_nil (node)) | |||
703 | { | |||
704 | node = tree->parent_node; | |||
705 | tree = tree->parent_tree; | |||
706 | } | |||
707 | } | |||
708 | while (node); | |||
709 | } | |||
710 | #endif | |||
711 | /* Assume tree is the root node as it doesn't set DESCENDANTS_INVALID above. | |||
712 | */ | |||
713 | void | |||
714 | _ctk_rbtree_column_invalid (CtkRBTree *tree) | |||
715 | { | |||
716 | CtkRBNode *node; | |||
717 | ||||
718 | if (tree == NULL((void*)0)) | |||
719 | return; | |||
720 | ||||
721 | node = _ctk_rbtree_first (tree); | |||
722 | ||||
723 | do | |||
724 | { | |||
725 | if (! (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID )?(!(0)):(0)):(0)))) | |||
726 | CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_COLUMN_INVALID)do{ (node->flags|=CTK_RBNODE_COLUMN_INVALID); }while (0); | |||
727 | CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_DESCENDANTS_INVALID)do{ (node->flags|=CTK_RBNODE_DESCENDANTS_INVALID); }while ( 0); | |||
728 | ||||
729 | if (node->children) | |||
730 | _ctk_rbtree_column_invalid (node->children); | |||
731 | } | |||
732 | while ((node = _ctk_rbtree_next (tree, node)) != NULL((void*)0)); | |||
733 | } | |||
734 | ||||
735 | void | |||
736 | _ctk_rbtree_mark_invalid (CtkRBTree *tree) | |||
737 | { | |||
738 | CtkRBNode *node; | |||
739 | ||||
740 | if (tree == NULL((void*)0)) | |||
741 | return; | |||
742 | ||||
743 | node = _ctk_rbtree_first (tree); | |||
744 | ||||
745 | do | |||
746 | { | |||
747 | CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_INVALID)do{ (node->flags|=CTK_RBNODE_INVALID); }while (0); | |||
748 | CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_DESCENDANTS_INVALID)do{ (node->flags|=CTK_RBNODE_DESCENDANTS_INVALID); }while ( 0); | |||
749 | ||||
750 | if (node->children) | |||
751 | _ctk_rbtree_mark_invalid (node->children); | |||
752 | } | |||
753 | while ((node = _ctk_rbtree_next (tree, node)) != NULL((void*)0)); | |||
754 | } | |||
755 | ||||
756 | void | |||
757 | _ctk_rbtree_set_fixed_height (CtkRBTree *tree, | |||
758 | gint height, | |||
759 | gboolean mark_valid) | |||
760 | { | |||
761 | CtkRBNode *node; | |||
762 | ||||
763 | if (tree == NULL((void*)0)) | |||
764 | return; | |||
765 | ||||
766 | node = _ctk_rbtree_first (tree); | |||
767 | ||||
768 | do | |||
769 | { | |||
770 | if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID )?(!(0)):(0)):(0))) | |||
771 | { | |||
772 | _ctk_rbtree_node_set_height (tree, node, height); | |||
773 | if (mark_valid) | |||
774 | _ctk_rbtree_node_mark_valid (tree, node); | |||
775 | } | |||
776 | ||||
777 | if (node->children) | |||
778 | _ctk_rbtree_set_fixed_height (node->children, height, mark_valid); | |||
779 | } | |||
780 | while ((node = _ctk_rbtree_next (tree, node)) != NULL((void*)0)); | |||
781 | } | |||
782 | ||||
783 | static void | |||
784 | reorder_prepare (CtkRBTree *tree G_GNUC_UNUSED__attribute__ ((__unused__)), | |||
785 | CtkRBNode *node, | |||
786 | gpointer data G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
787 | { | |||
788 | node->offset -= node->left->offset + node->right->offset; | |||
789 | CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_DESCENDANTS_INVALID)do{ (node->flags&=~(CTK_RBNODE_DESCENDANTS_INVALID)); } while (0); | |||
790 | } | |||
791 | ||||
792 | static void | |||
793 | reorder_fixup (CtkRBTree *tree, | |||
794 | CtkRBNode *node, | |||
795 | gpointer data G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
796 | { | |||
797 | node->offset += node->left->offset + node->right->offset; | |||
798 | node->count = 1 + node->left->count + node->right->count; | |||
799 | _fixup_validation (tree, node); | |||
800 | _fixup_total_count (tree, node); | |||
801 | } | |||
802 | ||||
803 | static void | |||
804 | reorder_copy_node (CtkRBTree *tree, | |||
805 | CtkRBNode *to, | |||
806 | CtkRBNode *from) | |||
807 | { | |||
808 | to->flags = (to->flags & CTK_RBNODE_NON_COLORS) | CTK_RBNODE_GET_COLOR (from)(from?(((from->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)? CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK); | |||
809 | ||||
810 | to->left = from->left; | |||
811 | if (!_ctk_rbtree_is_nil (to->left)) | |||
812 | to->left->parent = to; | |||
813 | ||||
814 | to->right = from->right; | |||
815 | if (!_ctk_rbtree_is_nil (to->right)) | |||
816 | to->right->parent = to; | |||
817 | ||||
818 | to->parent = from->parent; | |||
819 | if (_ctk_rbtree_is_nil (to->parent)) | |||
820 | tree->root = to; | |||
821 | else if (to->parent->left == from) | |||
822 | to->parent->left = to; | |||
823 | else if (to->parent->right == from) | |||
824 | to->parent->right = to; | |||
825 | } | |||
826 | ||||
827 | /* It basically pulls everything out of the tree, rearranges it, and puts it | |||
828 | * back together. Our strategy is to keep the old RBTree intact, and just | |||
829 | * rearrange the contents. When that is done, we go through and update the | |||
830 | * heights. There is probably a more elegant way to write this function. If | |||
831 | * anyone wants to spend the time writing it, patches will be accepted. | |||
832 | */ | |||
833 | void | |||
834 | _ctk_rbtree_reorder (CtkRBTree *tree, | |||
835 | gint *new_order, | |||
836 | gint length) | |||
837 | { | |||
838 | CtkRBNode **nodes; | |||
839 | CtkRBNode *node; | |||
840 | gint i, j; | |||
841 | ||||
842 | g_return_if_fail (tree != NULL)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree != NULL"); return; } } while (0); | |||
843 | g_return_if_fail (length > 0)do { if ((length > 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "length > 0"); return ; } } while (0); | |||
844 | g_return_if_fail (tree->root->count == length)do { if ((tree->root->count == length)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree->root->count == length" ); return; } } while (0); | |||
845 | ||||
846 | nodes = g_new (CtkRBNode *, length)((CtkRBNode * *) g_malloc_n ((length), sizeof (CtkRBNode *))); | |||
847 | ||||
848 | _ctk_rbtree_traverse (tree, tree->root, G_PRE_ORDER, reorder_prepare, NULL((void*)0)); | |||
849 | ||||
850 | for (node = _ctk_rbtree_first (tree), i = 0; | |||
851 | node; | |||
852 | node = _ctk_rbtree_next (tree, node), i++) | |||
853 | { | |||
854 | nodes[i] = node; | |||
855 | } | |||
856 | ||||
857 | for (i = 0; i < length; i++) | |||
858 | { | |||
859 | CtkRBNode tmp = { 0, }; | |||
860 | GSList *l, *cycle = NULL((void*)0); | |||
861 | ||||
862 | tmp.offset = -1; | |||
863 | ||||
864 | /* already swapped */ | |||
865 | if (nodes[i] == NULL((void*)0)) | |||
866 | continue; | |||
867 | /* no need to swap */ | |||
868 | if (new_order[i] == i) | |||
869 | continue; | |||
870 | ||||
871 | /* make a list out of the pending nodes */ | |||
872 | for (j = i; new_order[j] != i; j = new_order[j]) | |||
873 | { | |||
874 | cycle = g_slist_prepend (cycle, nodes[j]); | |||
875 | nodes[j] = NULL((void*)0); | |||
876 | } | |||
877 | ||||
878 | node = nodes[j]; | |||
879 | reorder_copy_node (tree, &tmp, node); | |||
880 | for (l = cycle; l; l = l->next) | |||
881 | { | |||
882 | reorder_copy_node (tree, node, l->data); | |||
883 | node = l->data; | |||
884 | } | |||
885 | ||||
886 | reorder_copy_node (tree, node, &tmp); | |||
887 | nodes[j] = NULL((void*)0); | |||
888 | g_slist_free (cycle); | |||
889 | } | |||
890 | ||||
891 | _ctk_rbtree_traverse (tree, tree->root, G_POST_ORDER, reorder_fixup, NULL((void*)0)); | |||
892 | ||||
893 | g_free (nodes); | |||
894 | } | |||
895 | ||||
896 | /** | |||
897 | * _ctk_rbtree_contains: | |||
898 | * @tree: a tree | |||
899 | * @potential_child: a potential child of @tree | |||
900 | * | |||
901 | * Checks if @potential_child is a child (direct or via intermediate | |||
902 | * trees) of @tree. | |||
903 | * | |||
904 | * Returns: %TRUE if @potentitial_child is a child of @tree. | |||
905 | **/ | |||
906 | gboolean | |||
907 | _ctk_rbtree_contains (CtkRBTree *tree, | |||
908 | CtkRBTree *potential_child) | |||
909 | { | |||
910 | g_return_val_if_fail (tree != NULL, FALSE)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree != NULL"); return ( (0)); } } while (0); | |||
911 | g_return_val_if_fail (potential_child != NULL, FALSE)do { if ((potential_child != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "potential_child != NULL" ); return ((0)); } } while (0); | |||
912 | ||||
913 | do { | |||
914 | potential_child = potential_child->parent_tree; | |||
915 | if (potential_child == tree) | |||
916 | return TRUE(!(0)); | |||
917 | } while (potential_child != NULL((void*)0)); | |||
918 | ||||
919 | return FALSE(0); | |||
920 | } | |||
921 | ||||
922 | gint | |||
923 | _ctk_rbtree_node_find_offset (CtkRBTree *tree, | |||
924 | CtkRBNode *node) | |||
925 | { | |||
926 | gint retval; | |||
927 | ||||
928 | g_assert (node)do { if (node) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 928, ((const char*) (__func__)), "node"); } while (0); | |||
929 | g_assert (node->left)do { if (node->left) ; else g_assertion_message_expr ("Ctk" , "ctkrbtree.c", 929, ((const char*) (__func__)), "node->left" ); } while (0); | |||
930 | ||||
931 | retval = node->left->offset; | |||
932 | ||||
933 | while (tree && node && !_ctk_rbtree_is_nil (node)) | |||
934 | { | |||
935 | CtkRBNode *last; | |||
936 | ||||
937 | last = node; | |||
938 | node = node->parent; | |||
939 | ||||
940 | /* Add left branch, plus children, iff we came from the right */ | |||
941 | if (node->right == last) | |||
942 | retval += node->offset - node->right->offset; | |||
943 | ||||
944 | if (_ctk_rbtree_is_nil (node)) | |||
945 | { | |||
946 | node = tree->parent_node; | |||
947 | tree = tree->parent_tree; | |||
948 | ||||
949 | /* Add the parent node, plus the left branch. */ | |||
950 | if (node) | |||
951 | retval += node->left->offset + CTK_RBNODE_GET_HEIGHT (node)(node->offset-(node->left->offset+node->right-> offset+(node->children?node->children->root->offset :0))); | |||
952 | } | |||
953 | } | |||
954 | return retval; | |||
955 | } | |||
956 | ||||
957 | guint | |||
958 | _ctk_rbtree_node_get_index (CtkRBTree *tree, | |||
959 | CtkRBNode *node) | |||
960 | { | |||
961 | guint retval; | |||
962 | ||||
963 | g_assert (node)do { if (node) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 963, ((const char*) (__func__)), "node"); } while (0); | |||
964 | g_assert (node->left)do { if (node->left) ; else g_assertion_message_expr ("Ctk" , "ctkrbtree.c", 964, ((const char*) (__func__)), "node->left" ); } while (0); | |||
965 | ||||
966 | retval = node->left->total_count; | |||
967 | ||||
968 | while (tree && node && !_ctk_rbtree_is_nil (node)) | |||
969 | { | |||
970 | CtkRBNode *last; | |||
971 | ||||
972 | last = node; | |||
973 | node = node->parent; | |||
974 | ||||
975 | /* Add left branch, plus children, iff we came from the right */ | |||
976 | if (node->right == last) | |||
977 | retval += node->total_count - node->right->total_count; | |||
978 | ||||
979 | if (_ctk_rbtree_is_nil (node)) | |||
980 | { | |||
981 | node = tree->parent_node; | |||
982 | tree = tree->parent_tree; | |||
983 | ||||
984 | /* Add the parent node, plus the left branch. */ | |||
985 | if (node) | |||
986 | retval += node->left->total_count + 1; /* 1 == CTK_RBNODE_GET_PARITY() */ | |||
987 | } | |||
988 | } | |||
989 | ||||
990 | return retval; | |||
991 | } | |||
992 | ||||
993 | static gint | |||
994 | ctk_rbtree_real_find_offset (CtkRBTree *tree, | |||
995 | gint height, | |||
996 | CtkRBTree **new_tree, | |||
997 | CtkRBNode **new_node) | |||
998 | { | |||
999 | CtkRBNode *tmp_node; | |||
1000 | ||||
1001 | g_assert (tree)do { if (tree) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1001, ((const char*) (__func__)), "tree"); } while (0); | |||
1002 | ||||
1003 | if (height < 0) | |||
1004 | { | |||
1005 | *new_tree = NULL((void*)0); | |||
1006 | *new_node = NULL((void*)0); | |||
1007 | ||||
1008 | return 0; | |||
1009 | } | |||
1010 | ||||
1011 | ||||
1012 | tmp_node = tree->root; | |||
1013 | while (!_ctk_rbtree_is_nil (tmp_node) && | |||
1014 | (tmp_node->left->offset > height || | |||
1015 | (tmp_node->offset - tmp_node->right->offset) < height)) | |||
1016 | { | |||
1017 | if (tmp_node->left->offset > height) | |||
1018 | tmp_node = tmp_node->left; | |||
1019 | else | |||
1020 | { | |||
1021 | height -= (tmp_node->offset - tmp_node->right->offset); | |||
1022 | tmp_node = tmp_node->right; | |||
1023 | } | |||
1024 | } | |||
1025 | if (_ctk_rbtree_is_nil (tmp_node)) | |||
1026 | { | |||
1027 | *new_tree = NULL((void*)0); | |||
1028 | *new_node = NULL((void*)0); | |||
1029 | return 0; | |||
1030 | } | |||
1031 | if (tmp_node->children) | |||
1032 | { | |||
1033 | if ((tmp_node->offset - | |||
1034 | tmp_node->right->offset - | |||
1035 | tmp_node->children->root->offset) > height) | |||
1036 | { | |||
1037 | *new_tree = tree; | |||
1038 | *new_node = tmp_node; | |||
1039 | return (height - tmp_node->left->offset); | |||
1040 | } | |||
1041 | return ctk_rbtree_real_find_offset (tmp_node->children, | |||
1042 | height - tmp_node->left->offset - | |||
1043 | (tmp_node->offset - | |||
1044 | tmp_node->left->offset - | |||
1045 | tmp_node->right->offset - | |||
1046 | tmp_node->children->root->offset), | |||
1047 | new_tree, | |||
1048 | new_node); | |||
1049 | } | |||
1050 | *new_tree = tree; | |||
1051 | *new_node = tmp_node; | |||
1052 | return (height - tmp_node->left->offset); | |||
1053 | } | |||
1054 | ||||
1055 | gint | |||
1056 | _ctk_rbtree_find_offset (CtkRBTree *tree, | |||
1057 | gint height, | |||
1058 | CtkRBTree **new_tree, | |||
1059 | CtkRBNode **new_node) | |||
1060 | { | |||
1061 | g_assert (tree)do { if (tree) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1061, ((const char*) (__func__)), "tree"); } while (0); | |||
1062 | ||||
1063 | if ((height < 0) || | |||
1064 | (height >= tree->root->offset)) | |||
1065 | { | |||
1066 | *new_tree = NULL((void*)0); | |||
1067 | *new_node = NULL((void*)0); | |||
1068 | ||||
1069 | return 0; | |||
1070 | } | |||
1071 | return ctk_rbtree_real_find_offset (tree, height, new_tree, new_node); | |||
1072 | } | |||
1073 | ||||
1074 | gboolean | |||
1075 | _ctk_rbtree_find_index (CtkRBTree *tree, | |||
1076 | guint index, | |||
1077 | CtkRBTree **new_tree, | |||
1078 | CtkRBNode **new_node) | |||
1079 | { | |||
1080 | CtkRBNode *tmp_node; | |||
1081 | ||||
1082 | g_assert (tree)do { if (tree) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1082, ((const char*) (__func__)), "tree"); } while (0); | |||
1083 | ||||
1084 | tmp_node = tree->root; | |||
1085 | while (!_ctk_rbtree_is_nil (tmp_node)) | |||
1086 | { | |||
1087 | if (tmp_node->left->total_count > index) | |||
1088 | { | |||
1089 | tmp_node = tmp_node->left; | |||
1090 | } | |||
1091 | else if (tmp_node->total_count - tmp_node->right->total_count <= index) | |||
1092 | { | |||
1093 | index -= tmp_node->total_count - tmp_node->right->total_count; | |||
1094 | tmp_node = tmp_node->right; | |||
1095 | } | |||
1096 | else | |||
1097 | { | |||
1098 | index -= tmp_node->left->total_count; | |||
1099 | break; | |||
1100 | } | |||
1101 | } | |||
1102 | if (_ctk_rbtree_is_nil (tmp_node)) | |||
1103 | { | |||
1104 | *new_tree = NULL((void*)0); | |||
1105 | *new_node = NULL((void*)0); | |||
1106 | return FALSE(0); | |||
1107 | } | |||
1108 | ||||
1109 | if (index > 0) | |||
1110 | { | |||
1111 | g_assert (tmp_node->children)do { if (tmp_node->children) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1111, ((const char*) (__func__)), "tmp_node->children" ); } while (0); | |||
1112 | ||||
1113 | return _ctk_rbtree_find_index (tmp_node->children, | |||
1114 | index - 1, | |||
1115 | new_tree, | |||
1116 | new_node); | |||
1117 | } | |||
1118 | ||||
1119 | *new_tree = tree; | |||
1120 | *new_node = tmp_node; | |||
1121 | return TRUE(!(0)); | |||
1122 | } | |||
1123 | ||||
1124 | void | |||
1125 | _ctk_rbtree_remove_node (CtkRBTree *tree, | |||
1126 | CtkRBNode *node) | |||
1127 | { | |||
1128 | CtkRBNode *x, *y; | |||
1129 | gint y_height; | |||
1130 | guint y_total_count; | |||
1131 | ||||
1132 | g_return_if_fail (tree != NULL)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree != NULL"); return; } } while (0); | |||
1133 | g_return_if_fail (node != NULL)do { if ((node != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "node != NULL"); return; } } while (0); | |||
1134 | ||||
1135 | ||||
1136 | #ifdef G_ENABLE_DEBUG1 | |||
1137 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
1138 | { | |||
1139 | GString *s; | |||
1140 | ||||
1141 | s = g_string_new (""); | |||
1142 | g_string_append_printf (s, "_ctk_rbtree_remove_node: %p\n", node); | |||
1143 | _ctk_rbtree_debug_spew (tree, s); | |||
1144 | g_message ("%s", s->str); | |||
1145 | g_string_free (s, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); | |||
1146 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "1146", tree); | |||
1147 | } | |||
1148 | #endif | |||
1149 | ||||
1150 | /* make sure we're deleting a node that's actually in the tree */ | |||
1151 | for (x = node; !_ctk_rbtree_is_nil (x->parent); x = x->parent) | |||
1152 | ; | |||
1153 | g_return_if_fail (x == tree->root)do { if ((x == tree->root)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "x == tree->root"); return ; } } while (0); | |||
1154 | ||||
1155 | #ifdef G_ENABLE_DEBUG1 | |||
1156 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
1157 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "1157", tree); | |||
1158 | #endif | |||
1159 | ||||
1160 | if (_ctk_rbtree_is_nil (node->left) || | |||
1161 | _ctk_rbtree_is_nil (node->right)) | |||
1162 | { | |||
1163 | y = node; | |||
1164 | } | |||
1165 | else | |||
1166 | { | |||
1167 | y = node->right; | |||
1168 | ||||
1169 | while (!_ctk_rbtree_is_nil (y->left)) | |||
1170 | y = y->left; | |||
1171 | } | |||
1172 | ||||
1173 | y_height = CTK_RBNODE_GET_HEIGHT (y)(y->offset-(y->left->offset+y->right->offset+( y->children?y->children->root->offset:0))) | |||
1174 | + (y->children ? y->children->root->offset : 0); | |||
1175 | y_total_count = 1 + (y->children ? y->children->root->total_count : 0); | |||
1176 | ||||
1177 | /* x is y's only child, or nil */ | |||
1178 | if (!_ctk_rbtree_is_nil (y->left)) | |||
1179 | x = y->left; | |||
1180 | else | |||
1181 | x = y->right; | |||
1182 | ||||
1183 | /* remove y from the parent chain */ | |||
1184 | if (!_ctk_rbtree_is_nil (x)) | |||
1185 | x->parent = y->parent; | |||
1186 | if (!_ctk_rbtree_is_nil (y->parent)) | |||
1187 | { | |||
1188 | if (y == y->parent->left) | |||
1189 | y->parent->left = x; | |||
1190 | else | |||
1191 | y->parent->right = x; | |||
1192 | } | |||
1193 | else | |||
1194 | { | |||
1195 | tree->root = x; | |||
1196 | } | |||
1197 | ||||
1198 | /* We need to clean up the validity of the tree. | |||
1199 | */ | |||
1200 | ctk_rbnode_adjust (tree, y, -1, - y_total_count, - y_height); | |||
1201 | ||||
1202 | if (CTK_RBNODE_GET_COLOR (y)(y?(((y->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)?CTK_RBNODE_RED :CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_BLACK) | |||
1203 | _ctk_rbtree_remove_node_fixup (tree, x, y->parent); | |||
1204 | ||||
1205 | if (y != node) | |||
1206 | { | |||
1207 | gint node_height, node_total_count; | |||
1208 | ||||
1209 | /* We want to see how much we remove from the aggregate values. | |||
1210 | * This is all the children we remove plus the node's values. | |||
1211 | */ | |||
1212 | node_height = CTK_RBNODE_GET_HEIGHT (node)(node->offset-(node->left->offset+node->right-> offset+(node->children?node->children->root->offset :0))) | |||
1213 | + (node->children ? node->children->root->offset : 0); | |||
1214 | node_total_count = 1 | |||
1215 | + (node->children ? node->children->root->total_count : 0); | |||
1216 | ||||
1217 | /* Move the node over */ | |||
1218 | if (CTK_RBNODE_GET_COLOR (node)(node?(((node->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)? CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) != CTK_RBNODE_GET_COLOR (y)(y?(((y->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)?CTK_RBNODE_RED :CTK_RBNODE_BLACK):CTK_RBNODE_BLACK)) | |||
1219 | y->flags ^= (CTK_RBNODE_BLACK | CTK_RBNODE_RED); | |||
1220 | ||||
1221 | y->left = node->left; | |||
1222 | if (!_ctk_rbtree_is_nil (y->left)) | |||
1223 | y->left->parent = y; | |||
1224 | y->right = node->right; | |||
1225 | if (!_ctk_rbtree_is_nil (y->right)) | |||
1226 | y->right->parent = y; | |||
1227 | y->parent = node->parent; | |||
1228 | if (!_ctk_rbtree_is_nil (y->parent)) | |||
1229 | { | |||
1230 | if (y->parent->left == node) | |||
1231 | y->parent->left = y; | |||
1232 | else | |||
1233 | y->parent->right = y; | |||
1234 | } | |||
1235 | else | |||
1236 | { | |||
1237 | tree->root = y; | |||
1238 | } | |||
1239 | y->count = node->count; | |||
1240 | y->total_count = node->total_count; | |||
1241 | y->offset = node->offset; | |||
1242 | ||||
1243 | ctk_rbnode_adjust (tree, y, | |||
1244 | 0, | |||
1245 | y_total_count - node_total_count, | |||
1246 | y_height - node_height); | |||
1247 | } | |||
1248 | ||||
1249 | _ctk_rbnode_free (node); | |||
1250 | ||||
1251 | #ifdef G_ENABLE_DEBUG1 | |||
1252 | if (CTK_DEBUG_CHECK (TREE)(ctk_get_debug_flags () & CTK_DEBUG_TREE)) | |||
1253 | { | |||
1254 | GString *s; | |||
1255 | ||||
1256 | s = g_string_new ("_ctk_rbtree_remove_node finished...\n"); | |||
1257 | _ctk_rbtree_debug_spew (tree, s); | |||
1258 | g_message ("%s", s->str); | |||
1259 | g_string_free (s, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); | |||
1260 | _ctk_rbtree_test (G_STRLOC"ctkrbtree.c" ":" "1260", tree); | |||
1261 | } | |||
1262 | #endif | |||
1263 | } | |||
1264 | ||||
1265 | CtkRBNode * | |||
1266 | _ctk_rbtree_first (CtkRBTree *tree) | |||
1267 | { | |||
1268 | CtkRBNode *node; | |||
1269 | ||||
1270 | node = tree->root; | |||
1271 | ||||
1272 | if (_ctk_rbtree_is_nil (node)) | |||
1273 | return NULL((void*)0); | |||
1274 | ||||
1275 | while (!_ctk_rbtree_is_nil (node->left)) | |||
1276 | node = node->left; | |||
1277 | ||||
1278 | return node; | |||
1279 | } | |||
1280 | ||||
1281 | CtkRBNode * | |||
1282 | _ctk_rbtree_next (CtkRBTree *tree, | |||
1283 | CtkRBNode *node) | |||
1284 | { | |||
1285 | g_return_val_if_fail (tree != NULL, NULL)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree != NULL"); return ( ((void*)0)); } } while (0); | |||
1286 | g_return_val_if_fail (node != NULL, NULL)do { if ((node != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "node != NULL"); return ( ((void*)0)); } } while (0); | |||
1287 | ||||
1288 | /* Case 1: the node's below us. */ | |||
1289 | if (!_ctk_rbtree_is_nil (node->right)) | |||
1290 | { | |||
1291 | node = node->right; | |||
1292 | while (!_ctk_rbtree_is_nil (node->left)) | |||
1293 | node = node->left; | |||
1294 | return node; | |||
1295 | } | |||
1296 | ||||
1297 | /* Case 2: it's an ancestor */ | |||
1298 | while (!_ctk_rbtree_is_nil (node->parent)) | |||
1299 | { | |||
1300 | if (node->parent->right == node) | |||
1301 | node = node->parent; | |||
1302 | else | |||
1303 | return (node->parent); | |||
1304 | } | |||
1305 | ||||
1306 | /* Case 3: There is no next node */ | |||
1307 | return NULL((void*)0); | |||
1308 | } | |||
1309 | ||||
1310 | CtkRBNode * | |||
1311 | _ctk_rbtree_prev (CtkRBTree *tree, | |||
1312 | CtkRBNode *node) | |||
1313 | { | |||
1314 | g_return_val_if_fail (tree != NULL, NULL)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree != NULL"); return ( ((void*)0)); } } while (0); | |||
1315 | g_return_val_if_fail (node != NULL, NULL)do { if ((node != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "node != NULL"); return ( ((void*)0)); } } while (0); | |||
1316 | ||||
1317 | /* Case 1: the node's below us. */ | |||
1318 | if (!_ctk_rbtree_is_nil (node->left)) | |||
1319 | { | |||
1320 | node = node->left; | |||
1321 | while (!_ctk_rbtree_is_nil (node->right)) | |||
1322 | node = node->right; | |||
1323 | return node; | |||
1324 | } | |||
1325 | ||||
1326 | /* Case 2: it's an ancestor */ | |||
1327 | while (!_ctk_rbtree_is_nil (node->parent)) | |||
1328 | { | |||
1329 | if (node->parent->left == node) | |||
1330 | node = node->parent; | |||
1331 | else | |||
1332 | return (node->parent); | |||
1333 | } | |||
1334 | ||||
1335 | /* Case 3: There is no next node */ | |||
1336 | return NULL((void*)0); | |||
1337 | } | |||
1338 | ||||
1339 | void | |||
1340 | _ctk_rbtree_next_full (CtkRBTree *tree, | |||
1341 | CtkRBNode *node, | |||
1342 | CtkRBTree **new_tree, | |||
1343 | CtkRBNode **new_node) | |||
1344 | { | |||
1345 | g_return_if_fail (tree != NULL)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree != NULL"); return; } } while (0); | |||
1346 | g_return_if_fail (node != NULL)do { if ((node != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "node != NULL"); return; } } while (0); | |||
1347 | g_return_if_fail (new_tree != NULL)do { if ((new_tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "new_tree != NULL"); return ; } } while (0); | |||
1348 | g_return_if_fail (new_node != NULL)do { if ((new_node != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "new_node != NULL"); return ; } } while (0); | |||
1349 | ||||
1350 | if (node->children) | |||
1351 | { | |||
1352 | *new_tree = node->children; | |||
1353 | *new_node = (*new_tree)->root; | |||
1354 | while (!_ctk_rbtree_is_nil ((*new_node)->left)) | |||
1355 | *new_node = (*new_node)->left; | |||
1356 | return; | |||
1357 | } | |||
1358 | ||||
1359 | *new_tree = tree; | |||
1360 | *new_node = _ctk_rbtree_next (tree, node); | |||
1361 | ||||
1362 | while ((*new_node == NULL((void*)0)) && | |||
1363 | (*new_tree != NULL((void*)0))) | |||
1364 | { | |||
1365 | *new_node = (*new_tree)->parent_node; | |||
1366 | *new_tree = (*new_tree)->parent_tree; | |||
1367 | if (*new_tree) | |||
1368 | *new_node = _ctk_rbtree_next (*new_tree, *new_node); | |||
1369 | } | |||
1370 | } | |||
1371 | ||||
1372 | void | |||
1373 | _ctk_rbtree_prev_full (CtkRBTree *tree, | |||
1374 | CtkRBNode *node, | |||
1375 | CtkRBTree **new_tree, | |||
1376 | CtkRBNode **new_node) | |||
1377 | { | |||
1378 | g_return_if_fail (tree != NULL)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree != NULL"); return; } } while (0); | |||
1379 | g_return_if_fail (node != NULL)do { if ((node != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "node != NULL"); return; } } while (0); | |||
1380 | g_return_if_fail (new_tree != NULL)do { if ((new_tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "new_tree != NULL"); return ; } } while (0); | |||
1381 | g_return_if_fail (new_node != NULL)do { if ((new_node != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "new_node != NULL"); return ; } } while (0); | |||
1382 | ||||
1383 | *new_tree = tree; | |||
1384 | *new_node = _ctk_rbtree_prev (tree, node); | |||
1385 | ||||
1386 | if (*new_node == NULL((void*)0)) | |||
1387 | { | |||
1388 | *new_node = (*new_tree)->parent_node; | |||
1389 | *new_tree = (*new_tree)->parent_tree; | |||
1390 | } | |||
1391 | else | |||
1392 | { | |||
1393 | while ((*new_node)->children) | |||
1394 | { | |||
1395 | *new_tree = (*new_node)->children; | |||
1396 | *new_node = (*new_tree)->root; | |||
1397 | while (!_ctk_rbtree_is_nil ((*new_node)->right)) | |||
1398 | *new_node = (*new_node)->right; | |||
1399 | } | |||
1400 | } | |||
1401 | } | |||
1402 | ||||
1403 | gint | |||
1404 | _ctk_rbtree_get_depth (CtkRBTree *tree) | |||
1405 | { | |||
1406 | CtkRBTree *tmp_tree; | |||
1407 | gint depth = 0; | |||
1408 | ||||
1409 | tmp_tree = tree->parent_tree; | |||
1410 | while (tmp_tree) | |||
1411 | { | |||
1412 | ++depth; | |||
1413 | tmp_tree = tmp_tree->parent_tree; | |||
1414 | } | |||
1415 | ||||
1416 | return depth; | |||
1417 | } | |||
1418 | ||||
1419 | static void | |||
1420 | _ctk_rbtree_traverse_pre_order (CtkRBTree *tree, | |||
1421 | CtkRBNode *node, | |||
1422 | CtkRBTreeTraverseFunc func, | |||
1423 | gpointer data) | |||
1424 | { | |||
1425 | if (_ctk_rbtree_is_nil (node)) | |||
1426 | return; | |||
1427 | ||||
1428 | (* func) (tree, node, data); | |||
1429 | _ctk_rbtree_traverse_pre_order (tree, node->left, func, data); | |||
1430 | _ctk_rbtree_traverse_pre_order (tree, node->right, func, data); | |||
1431 | } | |||
1432 | ||||
1433 | static void | |||
1434 | _ctk_rbtree_traverse_post_order (CtkRBTree *tree, | |||
1435 | CtkRBNode *node, | |||
1436 | CtkRBTreeTraverseFunc func, | |||
1437 | gpointer data) | |||
1438 | { | |||
1439 | if (_ctk_rbtree_is_nil (node)) | |||
1440 | return; | |||
1441 | ||||
1442 | _ctk_rbtree_traverse_post_order (tree, node->left, func, data); | |||
1443 | _ctk_rbtree_traverse_post_order (tree, node->right, func, data); | |||
1444 | (* func) (tree, node, data); | |||
1445 | } | |||
1446 | ||||
1447 | void | |||
1448 | _ctk_rbtree_traverse (CtkRBTree *tree, | |||
1449 | CtkRBNode *node, | |||
1450 | GTraverseType order, | |||
1451 | CtkRBTreeTraverseFunc func, | |||
1452 | gpointer data) | |||
1453 | { | |||
1454 | g_return_if_fail (tree != NULL)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree != NULL"); return; } } while (0); | |||
1455 | g_return_if_fail (node != NULL)do { if ((node != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "node != NULL"); return; } } while (0); | |||
1456 | g_return_if_fail (func != NULL)do { if ((func != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "func != NULL"); return; } } while (0); | |||
1457 | g_return_if_fail (order <= G_LEVEL_ORDER)do { if ((order <= G_LEVEL_ORDER)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "order <= G_LEVEL_ORDER" ); return; } } while (0); | |||
1458 | ||||
1459 | switch (order) | |||
1460 | { | |||
1461 | case G_PRE_ORDER: | |||
1462 | _ctk_rbtree_traverse_pre_order (tree, node, func, data); | |||
1463 | break; | |||
1464 | case G_POST_ORDER: | |||
1465 | _ctk_rbtree_traverse_post_order (tree, node, func, data); | |||
1466 | break; | |||
1467 | case G_IN_ORDER: | |||
1468 | case G_LEVEL_ORDER: | |||
1469 | default: | |||
1470 | g_warning ("unsupported traversal order."); | |||
1471 | break; | |||
1472 | } | |||
1473 | } | |||
1474 | ||||
1475 | static inline | |||
1476 | void _fixup_validation (CtkRBTree *tree G_GNUC_UNUSED__attribute__ ((__unused__)), | |||
1477 | CtkRBNode *node) | |||
1478 | { | |||
1479 | if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID )?(!(0)):(0)):(0)) || | |||
1480 | CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID )?(!(0)):(0)):(0)) || | |||
1481 | CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID)(node->left?(((node->left->flags&CTK_RBNODE_DESCENDANTS_INVALID )==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0)) || | |||
1482 | CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID)(node->right?(((node->right->flags&CTK_RBNODE_DESCENDANTS_INVALID )==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0)) || | |||
1483 | (node->children != NULL((void*)0) && CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID)(node->children->root?(((node->children->root-> flags&CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)))) | |||
1484 | { | |||
1485 | CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_DESCENDANTS_INVALID)do{ (node->flags|=CTK_RBNODE_DESCENDANTS_INVALID); }while ( 0); | |||
1486 | } | |||
1487 | else | |||
1488 | { | |||
1489 | CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_DESCENDANTS_INVALID)do{ (node->flags&=~(CTK_RBNODE_DESCENDANTS_INVALID)); } while (0); | |||
1490 | } | |||
1491 | } | |||
1492 | ||||
1493 | static inline | |||
1494 | void _fixup_total_count (CtkRBTree *tree G_GNUC_UNUSED__attribute__ ((__unused__)), | |||
1495 | CtkRBNode *node) | |||
1496 | { | |||
1497 | node->total_count = 1 + | |||
1498 | (node->children != NULL((void*)0) ? node->children->root->total_count : 0) + | |||
1499 | node->left->total_count + node->right->total_count; | |||
1500 | } | |||
1501 | ||||
1502 | #ifdef G_ENABLE_DEBUG1 | |||
1503 | static guint | |||
1504 | get_total_count (CtkRBNode *node) | |||
1505 | { | |||
1506 | guint child_total = 0; | |||
1507 | ||||
1508 | child_total += (guint) node->left->total_count; | |||
1509 | child_total += (guint) node->right->total_count; | |||
1510 | ||||
1511 | if (node->children) | |||
1512 | child_total += (guint) node->children->root->total_count; | |||
1513 | ||||
1514 | return child_total + 1; | |||
1515 | } | |||
1516 | ||||
1517 | static guint | |||
1518 | count_total (CtkRBTree *tree, | |||
1519 | CtkRBNode *node) | |||
1520 | { | |||
1521 | guint res; | |||
1522 | ||||
1523 | if (_ctk_rbtree_is_nil (node)) | |||
1524 | return 0; | |||
1525 | ||||
1526 | res = | |||
1527 | count_total (tree, node->left) + | |||
1528 | count_total (tree, node->right) + | |||
1529 | (guint)1 + | |||
1530 | (node->children ? count_total (node->children, node->children->root) : 0); | |||
1531 | ||||
1532 | if (res != node->total_count) | |||
1533 | g_error ("total count incorrect for node"); | |||
1534 | ||||
1535 | if (get_total_count (node) != node->total_count) | |||
1536 | g_error ("Node has incorrect total count %u, should be %u", node->total_count, get_total_count (node)); | |||
1537 | ||||
1538 | return res; | |||
1539 | } | |||
1540 | ||||
1541 | static gint | |||
1542 | _count_nodes (CtkRBTree *tree, | |||
1543 | CtkRBNode *node) | |||
1544 | { | |||
1545 | gint res; | |||
1546 | if (_ctk_rbtree_is_nil (node)) | |||
1547 | return 0; | |||
1548 | ||||
1549 | g_assert (node->left)do { if (node->left) ; else g_assertion_message_expr ("Ctk" , "ctkrbtree.c", 1549, ((const char*) (__func__)), "node->left" ); } while (0); | |||
1550 | g_assert (node->right)do { if (node->right) ; else g_assertion_message_expr ("Ctk" , "ctkrbtree.c", 1550, ((const char*) (__func__)), "node->right" ); } while (0); | |||
1551 | ||||
1552 | res = (_count_nodes (tree, node->left) + | |||
1553 | _count_nodes (tree, node->right) + 1); | |||
1554 | ||||
1555 | if (res != node->count) | |||
1556 | g_error ("Tree failed"); | |||
1557 | return res; | |||
1558 | } | |||
1559 | ||||
1560 | static void | |||
1561 | _ctk_rbtree_test_height (CtkRBTree *tree, | |||
1562 | CtkRBNode *node) | |||
1563 | { | |||
1564 | gint computed_offset = 0; | |||
1565 | ||||
1566 | /* This whole test is sort of a useless truism. */ | |||
1567 | ||||
1568 | if (!_ctk_rbtree_is_nil (node->left)) | |||
1569 | computed_offset += node->left->offset; | |||
1570 | ||||
1571 | if (!_ctk_rbtree_is_nil (node->right)) | |||
1572 | computed_offset += node->right->offset; | |||
1573 | ||||
1574 | if (node->children && !_ctk_rbtree_is_nil (node->children->root)) | |||
1575 | computed_offset += node->children->root->offset; | |||
1576 | ||||
1577 | if (CTK_RBNODE_GET_HEIGHT (node)(node->offset-(node->left->offset+node->right-> offset+(node->children?node->children->root->offset :0))) + computed_offset != node->offset) | |||
1578 | g_error ("node has broken offset"); | |||
1579 | ||||
1580 | if (!_ctk_rbtree_is_nil (node->left)) | |||
1581 | _ctk_rbtree_test_height (tree, node->left); | |||
1582 | ||||
1583 | if (!_ctk_rbtree_is_nil (node->right)) | |||
1584 | _ctk_rbtree_test_height (tree, node->right); | |||
1585 | ||||
1586 | if (node->children && !_ctk_rbtree_is_nil (node->children->root)) | |||
1587 | _ctk_rbtree_test_height (node->children, node->children->root); | |||
1588 | } | |||
1589 | ||||
1590 | static void | |||
1591 | _ctk_rbtree_test_dirty (CtkRBTree *tree, | |||
1592 | CtkRBNode *node, | |||
1593 | gint expected_dirtyness) | |||
1594 | { | |||
1595 | ||||
1596 | if (expected_dirtyness) | |||
1597 | { | |||
1598 | g_assert (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID) ||do { if ((node?(((node->flags&CTK_RBNODE_COLUMN_INVALID )==CTK_RBNODE_COLUMN_INVALID)?(!(0)):(0)):(0)) || (node?(((node ->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID)?(!(0) ):(0)):(0)) || (node->left?(((node->left->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->right?(((node->right->flags &CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->children && (node-> children->root?(((node->children->root->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1602, ((const char*) (__func__)), "CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID) || CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID) || CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID) || CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID) || (node->children && CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID))" ); } while (0) | |||
1599 | CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID) ||do { if ((node?(((node->flags&CTK_RBNODE_COLUMN_INVALID )==CTK_RBNODE_COLUMN_INVALID)?(!(0)):(0)):(0)) || (node?(((node ->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID)?(!(0) ):(0)):(0)) || (node->left?(((node->left->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->right?(((node->right->flags &CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->children && (node-> children->root?(((node->children->root->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1602, ((const char*) (__func__)), "CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID) || CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID) || CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID) || CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID) || (node->children && CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID))" ); } while (0) | |||
1600 | CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID) ||do { if ((node?(((node->flags&CTK_RBNODE_COLUMN_INVALID )==CTK_RBNODE_COLUMN_INVALID)?(!(0)):(0)):(0)) || (node?(((node ->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID)?(!(0) ):(0)):(0)) || (node->left?(((node->left->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->right?(((node->right->flags &CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->children && (node-> children->root?(((node->children->root->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1602, ((const char*) (__func__)), "CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID) || CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID) || CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID) || CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID) || (node->children && CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID))" ); } while (0) | |||
1601 | CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID) ||do { if ((node?(((node->flags&CTK_RBNODE_COLUMN_INVALID )==CTK_RBNODE_COLUMN_INVALID)?(!(0)):(0)):(0)) || (node?(((node ->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID)?(!(0) ):(0)):(0)) || (node->left?(((node->left->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->right?(((node->right->flags &CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->children && (node-> children->root?(((node->children->root->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1602, ((const char*) (__func__)), "CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID) || CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID) || CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID) || CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID) || (node->children && CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID))" ); } while (0) | |||
1602 | (node->children && CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID)))do { if ((node?(((node->flags&CTK_RBNODE_COLUMN_INVALID )==CTK_RBNODE_COLUMN_INVALID)?(!(0)):(0)):(0)) || (node?(((node ->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID)?(!(0) ):(0)):(0)) || (node->left?(((node->left->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->right?(((node->right->flags &CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)) || (node->children && (node-> children->root?(((node->children->root->flags& CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0)))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1602, ((const char*) (__func__)), "CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID) || CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID) || CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID) || CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID) || (node->children && CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID))" ); } while (0); | |||
1603 | } | |||
1604 | else | |||
1605 | { | |||
1606 | g_assert (! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID) &&do { if (! (node?(((node->flags&CTK_RBNODE_COLUMN_INVALID )==CTK_RBNODE_COLUMN_INVALID)?(!(0)):(0)):(0)) && ! ( node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID )?(!(0)):(0)):(0))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1607, ((const char*) (__func__)), "! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID) && ! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)" ); } while (0) | |||
1607 | ! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID))do { if (! (node?(((node->flags&CTK_RBNODE_COLUMN_INVALID )==CTK_RBNODE_COLUMN_INVALID)?(!(0)):(0)):(0)) && ! ( node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID )?(!(0)):(0)):(0))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1607, ((const char*) (__func__)), "! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID) && ! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)" ); } while (0); | |||
1608 | if (!_ctk_rbtree_is_nil (node->left)) | |||
1609 | g_assert (! CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID))do { if (! (node->left?(((node->left->flags&CTK_RBNODE_DESCENDANTS_INVALID )==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1609, ((const char*) (__func__)), "! CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID)" ); } while (0); | |||
1610 | if (!_ctk_rbtree_is_nil (node->right)) | |||
1611 | g_assert (! CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID))do { if (! (node->right?(((node->right->flags&CTK_RBNODE_DESCENDANTS_INVALID )==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1611, ((const char*) (__func__)), "! CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID)" ); } while (0); | |||
1612 | if (node->children != NULL((void*)0)) | |||
1613 | g_assert (! CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID))do { if (! (node->children->root?(((node->children-> root->flags&CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0))) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c" , 1613, ((const char*) (__func__)), "! CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID)" ); } while (0); | |||
1614 | } | |||
1615 | ||||
1616 | if (!_ctk_rbtree_is_nil (node->left)) | |||
1617 | _ctk_rbtree_test_dirty (tree, node->left, CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID)(node->left?(((node->left->flags&CTK_RBNODE_DESCENDANTS_INVALID )==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))); | |||
1618 | if (!_ctk_rbtree_is_nil (node->right)) | |||
1619 | _ctk_rbtree_test_dirty (tree, node->right, CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID)(node->right?(((node->right->flags&CTK_RBNODE_DESCENDANTS_INVALID )==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))); | |||
1620 | if (node->children != NULL((void*)0) && !_ctk_rbtree_is_nil (node->children->root)) | |||
1621 | _ctk_rbtree_test_dirty (node->children, node->children->root, CTK_RBNODE_FLAG_SET (node->children->root, CTK_RBNODE_DESCENDANTS_INVALID)(node->children->root?(((node->children->root-> flags&CTK_RBNODE_DESCENDANTS_INVALID)==CTK_RBNODE_DESCENDANTS_INVALID )?(!(0)):(0)):(0))); | |||
1622 | } | |||
1623 | ||||
1624 | static void _ctk_rbtree_test_structure (CtkRBTree *tree); | |||
1625 | ||||
1626 | static void | |||
1627 | _ctk_rbtree_test_structure_helper (CtkRBTree *tree, | |||
1628 | CtkRBNode *node) | |||
1629 | { | |||
1630 | g_assert (!_ctk_rbtree_is_nil (node))do { if (!_ctk_rbtree_is_nil (node)) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1630, ((const char*) (__func__)), "!_ctk_rbtree_is_nil (node)" ); } while (0); | |||
1631 | ||||
1632 | g_assert (node->left != NULL)do { if (node->left != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1632, ((const char*) (__func__)), "node->left != NULL" ); } while (0); | |||
1633 | g_assert (node->right != NULL)do { if (node->right != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1633, ((const char*) (__func__)), "node->right != NULL" ); } while (0); | |||
1634 | g_assert (node->parent != NULL)do { if (node->parent != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1634, ((const char*) (__func__)), "node->parent != NULL" ); } while (0); | |||
1635 | ||||
1636 | if (!_ctk_rbtree_is_nil (node->left)) | |||
1637 | { | |||
1638 | g_assert (node->left->parent == node)do { if (node->left->parent == node) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1638, ((const char*) (__func__)), "node->left->parent == node" ); } while (0); | |||
1639 | _ctk_rbtree_test_structure_helper (tree, node->left); | |||
1640 | } | |||
1641 | if (!_ctk_rbtree_is_nil (node->right)) | |||
1642 | { | |||
1643 | g_assert (node->right->parent == node)do { if (node->right->parent == node) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1643, ((const char*) (__func__)), "node->right->parent == node" ); } while (0); | |||
1644 | _ctk_rbtree_test_structure_helper (tree, node->right); | |||
1645 | } | |||
1646 | ||||
1647 | if (node->children != NULL((void*)0)) | |||
1648 | { | |||
1649 | g_assert (node->children->parent_tree == tree)do { if (node->children->parent_tree == tree) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1649, ((const char*) (__func__)), "node->children->parent_tree == tree" ); } while (0); | |||
1650 | g_assert (node->children->parent_node == node)do { if (node->children->parent_node == node) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1650, ((const char*) (__func__)), "node->children->parent_node == node" ); } while (0); | |||
1651 | ||||
1652 | _ctk_rbtree_test_structure (node->children); | |||
1653 | } | |||
1654 | } | |||
1655 | static void | |||
1656 | _ctk_rbtree_test_structure (CtkRBTree *tree) | |||
1657 | { | |||
1658 | g_assert (tree->root)do { if (tree->root) ; else g_assertion_message_expr ("Ctk" , "ctkrbtree.c", 1658, ((const char*) (__func__)), "tree->root" ); } while (0); | |||
1659 | if (_ctk_rbtree_is_nil (tree->root)) | |||
1660 | return; | |||
1661 | ||||
1662 | g_assert (_ctk_rbtree_is_nil (tree->root->parent))do { if (_ctk_rbtree_is_nil (tree->root->parent)) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1662, ((const char*) (__func__)), "_ctk_rbtree_is_nil (tree->root->parent)" ); } while (0); | |||
1663 | _ctk_rbtree_test_structure_helper (tree, tree->root); | |||
1664 | } | |||
1665 | ||||
1666 | static void | |||
1667 | _ctk_rbtree_test (const gchar *where G_GNUC_UNUSED__attribute__ ((__unused__)), | |||
1668 | CtkRBTree *tree) | |||
1669 | { | |||
1670 | CtkRBTree *tmp_tree; | |||
1671 | ||||
1672 | if (tree == NULL((void*)0)) | |||
1673 | return; | |||
1674 | ||||
1675 | /* Test the entire tree */ | |||
1676 | tmp_tree = tree; | |||
1677 | while (tmp_tree->parent_tree) | |||
1678 | tmp_tree = tmp_tree->parent_tree; | |||
1679 | ||||
1680 | if (_ctk_rbtree_is_nil (tmp_tree->root)) | |||
1681 | return; | |||
1682 | ||||
1683 | _ctk_rbtree_test_structure (tmp_tree); | |||
1684 | ||||
1685 | g_assert ((_count_nodes (tmp_tree, tmp_tree->root->left) +do { if ((_count_nodes (tmp_tree, tmp_tree->root->left) + _count_nodes (tmp_tree, tmp_tree->root->right) + 1) == tmp_tree->root->count) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1686, ((const char*) (__func__)), "(_count_nodes (tmp_tree, tmp_tree->root->left) + _count_nodes (tmp_tree, tmp_tree->root->right) + 1) == tmp_tree->root->count" ); } while (0) | |||
1686 | _count_nodes (tmp_tree, tmp_tree->root->right) + 1) == tmp_tree->root->count)do { if ((_count_nodes (tmp_tree, tmp_tree->root->left) + _count_nodes (tmp_tree, tmp_tree->root->right) + 1) == tmp_tree->root->count) ; else g_assertion_message_expr ("Ctk", "ctkrbtree.c", 1686, ((const char*) (__func__)), "(_count_nodes (tmp_tree, tmp_tree->root->left) + _count_nodes (tmp_tree, tmp_tree->root->right) + 1) == tmp_tree->root->count" ); } while (0); | |||
1687 | ||||
1688 | ||||
1689 | _ctk_rbtree_test_height (tmp_tree, tmp_tree->root); | |||
1690 | _ctk_rbtree_test_dirty (tmp_tree, tmp_tree->root, CTK_RBNODE_FLAG_SET (tmp_tree->root, CTK_RBNODE_DESCENDANTS_INVALID)(tmp_tree->root?(((tmp_tree->root->flags&CTK_RBNODE_DESCENDANTS_INVALID )==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))); | |||
1691 | g_assert (count_total (tmp_tree, tmp_tree->root) == tmp_tree->root->total_count)do { if (count_total (tmp_tree, tmp_tree->root) == tmp_tree ->root->total_count) ; else g_assertion_message_expr ("Ctk" , "ctkrbtree.c", 1691, ((const char*) (__func__)), "count_total (tmp_tree, tmp_tree->root) == tmp_tree->root->total_count" ); } while (0); | |||
1692 | } | |||
1693 | ||||
1694 | static void | |||
1695 | _ctk_rbtree_debug_spew_helper (CtkRBTree *tree, | |||
1696 | CtkRBNode *node, | |||
1697 | GString *s, | |||
1698 | gint depth) | |||
1699 | { | |||
1700 | gint i; | |||
1701 | for (i = 0; i < depth; i++) | |||
1702 | g_string_append (s, "\t")(__builtin_constant_p ("\t") ? __extension__ ({ const char * const __val = ("\t"); g_string_append_len_inline (s, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, "\t", (gssize) -1) ); | |||
1703 | ||||
1704 | g_string_append_printf (s, "(%p - %s) (Offset %d) (Parity %d) (Validity %d%d%d)\n", | |||
1705 | node, | |||
1706 | (CTK_RBNODE_GET_COLOR (node)(node?(((node->flags&CTK_RBNODE_RED)==CTK_RBNODE_RED)? CTK_RBNODE_RED:CTK_RBNODE_BLACK):CTK_RBNODE_BLACK) == CTK_RBNODE_BLACK)?"BLACK":" RED ", | |||
1707 | node->offset, | |||
1708 | node->total_count, | |||
1709 | (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_DESCENDANTS_INVALID)(node?(((node->flags&CTK_RBNODE_DESCENDANTS_INVALID)== CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0)))?1:0, | |||
1710 | (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID )?(!(0)):(0)):(0)))?1:0, | |||
1711 | (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID )?(!(0)):(0)):(0)))?1:0); | |||
1712 | if (node->children != NULL((void*)0)) | |||
1713 | { | |||
1714 | g_string_append (s, "Looking at child.\n")(__builtin_constant_p ("Looking at child.\n") ? __extension__ ({ const char * const __val = ("Looking at child.\n"); g_string_append_len_inline (s, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (s, "Looking at child.\n", (gssize) -1)); | |||
1715 | _ctk_rbtree_debug_spew (node->children, s); | |||
1716 | g_string_append (s, "Done looking at child.\n")(__builtin_constant_p ("Done looking at child.\n") ? __extension__ ({ const char * const __val = ("Done looking at child.\n"); g_string_append_len_inline (s, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (s, "Done looking at child.\n", (gssize) -1)); | |||
1717 | } | |||
1718 | if (!_ctk_rbtree_is_nil (node->left)) | |||
1719 | { | |||
1720 | _ctk_rbtree_debug_spew_helper (tree, node->left, s, depth + 1); | |||
1721 | } | |||
1722 | if (!_ctk_rbtree_is_nil (node->right)) | |||
1723 | { | |||
1724 | _ctk_rbtree_debug_spew_helper (tree, node->right, s, depth + 1); | |||
1725 | } | |||
1726 | } | |||
1727 | ||||
1728 | static void | |||
1729 | _ctk_rbtree_debug_spew (CtkRBTree *tree, GString *s) | |||
1730 | { | |||
1731 | g_return_if_fail (tree != NULL)do { if ((tree != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "tree != NULL"); return; } } while (0); | |||
1732 | ||||
1733 | if (_ctk_rbtree_is_nil (tree->root)) | |||
1734 | g_string_append (s, "Empty tree...")(__builtin_constant_p ("Empty tree...") ? __extension__ ({ const char * const __val = ("Empty tree..."); g_string_append_len_inline (s, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (s, "Empty tree...", (gssize) -1)); | |||
1735 | else | |||
1736 | _ctk_rbtree_debug_spew_helper (tree, tree->root, s, 0); | |||
1737 | } | |||
1738 | #endif /* G_ENABLE_DEBUG */ |