Open SCAP Library

redblack.h
1 /*
2 * Copyright 2009 Red Hat Inc., Durham, North Carolina.
3 * All Rights Reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Authors:
20 * "Daniel Kopecek" <dkopecek@redhat.com>
21 */
22
23 #pragma once
24 #ifndef REDBLACK_H
25 #define REDBLACK_H
26
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <assert.h>
30 #include "../../../../common/util.h"
31
32 OSCAP_HIDDEN_START;
33
34 #ifndef NDEBUG
35 # define _E(exp) exp
36 #else
37 # define _E(exp) while(0)
38 #endif
39
40 #define XMALLOC malloc
41 #define XREALLOC realloc
42 #define XCALLOC calloc
43 #define XFREE free
44
45 #define SIDE_LEFT ((side_t)0)
46 #define SIDE_RGHT ((side_t)1)
47
48 #define COLOR_BLK 0
49 #define COLOR_RED 1
50
51 #define PREORDER 0
52 #define INORDER 1
53 #define POSTORDER 2
54 #define LRTDLAYER 3
55 #define RLTDLAYER 4
56
57 #if !defined (E_OK)
58 # define E_OK 0
59 #endif
60 #if !defined (E_FAIL)
61 # define E_FAIL 1
62 #endif
63 #if !defined (E_COLL)
64 # define E_COLL 2
65 #endif
66
67 #define __NAME_PREFIX__ ___rb_
68 #define __TREETYPE_PREFIX rbtree_
69 #define __NODETYPE_PREFIX rbnode_
70 #define __NODETYPE_ATTRS__ __attribute__ ((packed))
71 #define __TREETYPE_ATTRS__ __attribute__ ((packed))
72
73 typedef uint8_t side_t;
74 typedef uint8_t color_t;
75
76 #define __MYCONCAT2(a, b) a ## b
77 #define __MYCONCAT3(a, b, c) a ## b ## c
78 #define CONCAT2(a, b) __MYCONCAT2(a, b)
79 #define CONCAT3(a, b, c) __MYCONCAT3(a, b, c)
80 #define EXPAND(a) a
81
82 #define TREETYPE(__t_name) struct CONCAT2(__TREETYPE_PREFIX, __t_name)
83 #define NODETYPE(__t_name) struct CONCAT2(__NODETYPE_PREFIX, __t_name)
84
85 /* Definition templates */
86 #define DEF_RBN_INITST(__t_name) int CONCAT3(__NAME_PREFIX__, __t_name, _initst) (TREETYPE(__t_name) *tree)
87
88 #define RBN_CREATE_NAME(__t_name) CONCAT3(__NAME_PREFIX__, __t_name, _create)
89 #define DEF_RBN_CREATE(__t_name) TREETYPE(__t_name) * RBN_CREATE_NAME(__t_name) (void)
90 #define RB_CREATE RBN_CREATE_NAME
91
92 #define RBN_NEWNODE_NAME(__t_name) CONCAT3(__NAME_PREFIX__, __t_name, _newnode)
93 #define DEF_RBN_NEWNODE(__t_name) NODETYPE(__t_name) * RBN_NEWNODE_NAME(__t_name) (void)
94 #define RB_NEWNODE RBN_NEWNODE_NAME
95
96 #define RBN_INSERT_NAME(__t_name) CONCAT3(__NAME_PREFIX__, __t_name, _insert)
97 #define DEF_RBN_INSERT(__t_name) int RBN_INSERT_NAME(__t_name) (TREETYPE(__t_name) *tree, NODETYPE(__t_name) *new_node)
98 #define RB_INSERT RBN_INSERT_NAME
99
100 #define RBN_SEARCH_NAME(__t_name) CONCAT3(__NAME_PREFIX__, __t_name, _search)
101 #define DEF_RBN_SEARCH(__t_name) NODETYPE(__t_name) * RBN_SEARCH_NAME(__t_name) (TREETYPE(__t_name) *tree, const NODETYPE(__t_name) *k_node)
102 #define RB_SEARCH RBN_SEARCH_NAME
103
104 #define DEF_RBN_DELETE(__t_name) int CONCAT3(__NAME_PREFIX__, __t_name, _delete) (TREETYPE(__t_name) *tree, const NODETYPE(__t_name) *k_node)
105
106 #define DEF_RBN_REMOVE(__t_name) DEF_RBN_DELETE(__t_name)
107
108 #define DEF_RBN_NODE_LEFT(__t_name) NODETYPE(__t_name) * CONCAT3(__NAME_PREFIX__, __t_name, _getLeftNode) (NODETYPE(__t_name) *node)
109 #define DEF_RBN_NODE_RGHT(__t_name) NODETYPE(__t_name) * CONCAT3(__NAME_PREFIX__, __t_name, _getRghtNode) (NODETYPE(__t_name) *node)
110 #define DEF_RBN_NODE_RIGHT(__t_name) RBN_NODE_RGHT(__t_name)
111
112 #define DEF_RBN_NODE_COLOR(__t_name) color_t CONCAT3(__NAME_PREFIX__, __t_name, _getColor) (NODETYPE(__t_name) *node)
113 #define DEF_RBN_NODE_SIDE(__t_name) side_t CONCAT3(__NAME_PREFIX__, __t_name, _getSide) (NODETYPE(__t_name) *node)
114
115 #define DEF_RBN_ROT_R(__t_name) NODETYPE(__t_name) * CONCAT3(__NAME_PREFIX__, __t_name, _rotR) (NODETYPE(__t_name) *r)
116 #define DEF_RBN_ROT_L(__t_name) NODETYPE(__t_name) * CONCAT3(__NAME_PREFIX__, __t_name, _rotL) (NODETYPE(__t_name) *r)
117 #define DEF_RBN_ROT_RL(__t_name) NODETYPE(__t_name) * CONCAT3(__NAME_PREFIX__, __t_name, _rotRL) (NODETYPE(__t_name) *r)
118 #define DEF_RBN_ROT_LR(__t_name) NODETYPE(__t_name) * CONCAT3(__NAME_PREFIX__, __t_name, _rotLR) (NODETYPE(__t_name) *r)
119
120 #define ROTATE_ARR_NAME(__t_name) CONCAT3(__NAME_PREFIX__, __t_name, _rotate)
121
122 #define RBN_NODECMP_NAME(__t_name) CONCAT3(__NAME_PREFIX__, __t_name, _nodecmp)
123 #define DEF_RBN_NODECMP(__t_name) int RBN_NODECMP_NAME(__t_name) (const NODETYPE(__t_name) *a, const NODETYPE(__t_name) *b)
124 #define RBNODECMP DEF_RBN_NODECMP
125
126 #define RBN_NODEJOIN_NAME(__t_name) CONCAT3(__NAME_PREFIX__, __t_name, _nodejoin)
127 #define DEF_RBN_NODEJOIN(__t_name) NODETYPE(__t_name) * RBN_NODEJOIN_NAME(__t_name) (NODETYPE(__t_name) *a, NODETYPE(__t_name) *b)
128 #define RBNODEJOIN DEF_RBN_NODEJOIN
129
130 #define RBN_WALK_NAME(__t_name) CONCAT3(__NAME_PREFIX__, __t_name, _walk)
131 #define DEF_RBN_WALK(__t_name) void RBN_WALK_NAME(__t_name) (TREETYPE(__t_name) *tree, uint8_t order, void (*callback)(NODETYPE(__t_name) *, void *), void *cbarg)
132 #define RB_WALK RBN_WALK_NAME
133
134 #define RBN_CALLBACK_NAME(__t_name, myname) CONCAT3(__t_name, _CB_, myname)
135 #define DEF_RBN_CALLBACK(__t_name, myname) void RBN_CALLBACK_NAME(__t_name, myname) (NODETYPE(__t_name) *node, void *cbarg)
136 #define RBCBNAME RBN_CALLBACK_NAME
137 #define RBCALLBACK DEF_RBN_CALLBACK
138
139 #define NOARG 0
140
141 /* Main template */
142 #define DEFRBTREE(__t_name, __u_nitem) \
143 NODETYPE(__t_name) { \
144 /* META data */ \
145 NODETYPE(__t_name) *___child[2]; \
146 color_t ___c: 1; /* Node color */ \
147 side_t ___s: 1; /* Node side relative to parent */ \
148 /* USER data */ \
149 __u_nitem; \
150 } __NODETYPE_ATTRS__; \
151 \
152 TREETYPE(__t_name) { \
153 NODETYPE(__t_name) *root; \
154 size_t size; \
155 } __TREETYPE_ATTRS__; \
156 \
157 DEF_RBN_NODEJOIN(__t_name); \
158 DEF_RBN_NODECMP(__t_name); \
159 DEF_RBN_CREATE(__t_name); \
160 DEF_RBN_NEWNODE(__t_name); \
161 DEF_RBN_WALK(__t_name); \
162 DEF_RBN_INSERT(__t_name); \
163 DEF_RBN_SEARCH(__t_name)
164 /*
165 DEF_RBN_INITST(__t_name); \
166 DEF_RBN_SEARCH(__t_name, __keytype); \
167 DEF_RBN_DELETE(__t_name, __keytype); \
168 DEF_RBN_NODE_LEFT(__t_name); \
169 DEF_RBN_NODE_RGHT(__t_name); \
170 DEF_RBN_NODE_COLOR(__t_name); \
171 DEF_RBN_NODE_SIDE(__t_name)
172 */
173
174 #define __isRED(n) ((n)->___c == COLOR_RED)
175 #define isRED(n) (((n) == NULL) ? 0 : __isRED(n))
176 #define PTRMOVE(next) { \
177 ggp = grp; \
178 grp = par; \
179 par = cur; \
180 cur = next; }
181
182 #define lch (cur->___child[SIDE_LEFT])
183 #define rch (cur->___child[SIDE_RGHT])
184
185 /* Code templates */
186 //#define RBN_INITST()
187
188 #define RBN_NEWNODE_CODE(__t_name) \
189 DEF_RBN_NEWNODE(__t_name) { \
190 NODETYPE(__t_name) *new; \
191 new = XMALLOC(sizeof(NODETYPE(__t_name))); \
192 new->___s = 0; \
193 new->___c = 0; \
194 new->___child[0] = NULL; \
195 new->___child[1] = NULL; \
196 return (new); \
197 }
198
199 #define RBN_ROTATE_CODE(__t_name) \
200 static DEF_RBN_ROT_L(__t_name) { \
201 register NODETYPE(__t_name) *nr; \
202 \
203 nr = r->___child[SIDE_RGHT]; \
204 r->___child[SIDE_RGHT] = nr->___child[SIDE_LEFT]; \
205 nr->___child[SIDE_LEFT] = r; \
206 \
207 nr->___s = r->___s; \
208 r->___s = SIDE_LEFT; \
209 \
210 if (r->___child[SIDE_RGHT] != NULL) \
211 r->___child[SIDE_RGHT]->___s = SIDE_RGHT; \
212 \
213 if (nr->___child[SIDE_RGHT] != NULL) \
214 nr->___child[SIDE_RGHT]->___c = COLOR_BLK; \
215 \
216 return (nr); \
217 } \
218 \
219 static DEF_RBN_ROT_R(__t_name) { \
220 register NODETYPE(__t_name) *nr; \
221 \
222 nr = r->___child[SIDE_LEFT]; \
223 r->___child[SIDE_LEFT] = nr->___child[SIDE_RGHT]; \
224 nr->___child[SIDE_RGHT] = r; \
225 \
226 nr->___s = r->___s; \
227 r->___s = SIDE_RGHT; \
228 \
229 if (r->___child[SIDE_LEFT] != NULL) \
230 r->___child[SIDE_LEFT]->___s = SIDE_LEFT; \
231 \
232 if (nr->___child[SIDE_LEFT] != NULL) \
233 nr->___child[SIDE_LEFT]->___c = COLOR_BLK; \
234 \
235 return (nr); \
236 } \
237 \
238 static DEF_RBN_ROT_LR(__t_name) { \
239 register NODETYPE(__t_name) *nr; \
240 \
241 nr = r->___child[SIDE_RGHT]->___child[SIDE_LEFT]; \
242 nr->___s = r->___s; \
243 r->___s = SIDE_LEFT; \
244 r->___child[SIDE_RGHT]->___child[SIDE_LEFT] = nr->___child[SIDE_RGHT]; \
245 \
246 if (nr->___child[SIDE_RGHT] != NULL) \
247 nr->___child[SIDE_RGHT]->___s = SIDE_LEFT; \
248 \
249 nr->___child[SIDE_RGHT] = r->___child[SIDE_RGHT]; \
250 r->___child[SIDE_RGHT] = nr->___child[SIDE_LEFT]; \
251 \
252 if (nr->___child[SIDE_LEFT] != NULL) \
253 nr->___child[SIDE_LEFT]->___s = SIDE_RGHT; \
254 \
255 nr->___child[SIDE_LEFT] = r; \
256 nr->___child[SIDE_RGHT]->___c = COLOR_BLK; \
257 \
258 return (nr); \
259 } \
260 \
261 static DEF_RBN_ROT_RL(__t_name) { \
262 register NODETYPE(__t_name) *nr; \
263 \
264 nr = r->___child[SIDE_LEFT]->___child[SIDE_RGHT]; \
265 nr->___s = r->___s; \
266 r->___s = SIDE_RGHT; \
267 r->___child[SIDE_LEFT]->___child[SIDE_RGHT] = nr->___child[SIDE_LEFT]; \
268 \
269 if (nr->___child[SIDE_LEFT] != NULL) \
270 nr->___child[SIDE_LEFT]->___s = SIDE_RGHT; \
271 \
272 nr->___child[SIDE_LEFT] = r->___child[SIDE_LEFT]; \
273 r->___child[SIDE_LEFT] = nr->___child[SIDE_RGHT]; \
274 \
275 if (nr->___child[SIDE_RGHT] != NULL) \
276 nr->___child[SIDE_RGHT]->___s = SIDE_LEFT; \
277 \
278 nr->___child[SIDE_RGHT] = r; \
279 nr->___child[SIDE_LEFT]->___c = COLOR_BLK; \
280 \
281 return (nr); \
282 } \
283 \
284 static NODETYPE(__t_name) * (*ROTATE_ARR_NAME(__t_name)[4])(NODETYPE(__t_name) *) = { \
285 &CONCAT3(__NAME_PREFIX__, __t_name, _rotR), \
286 &CONCAT3(__NAME_PREFIX__, __t_name, _rotLR), \
287 &CONCAT3(__NAME_PREFIX__, __t_name, _rotRL), \
288 &CONCAT3(__NAME_PREFIX__, __t_name, _rotL) \
289 }
290
291 #define RBN_CREATE_CODE(__t_name) \
292 DEF_RBN_CREATE(__t_name) { \
293 TREETYPE(__t_name) *new = XMALLOC (sizeof (TREETYPE(__t_name))); \
294 new->root = NULL; \
295 new->size = 0; \
296 return (new); \
297 }
298
299 #define RBN_INSERT_CODE(__t_name) \
300 DEF_RBN_INSERT(__t_name) { \
301 NODETYPE(__t_name) *cur, *par, *grp, *ggp; \
302 side_t lastdir; \
303 int cmp; \
304 NODETYPE(__t_name) fake; \
305 \
306 fake.___c = COLOR_BLK; \
307 fake.___child[SIDE_RGHT] = tree->root; \
308 fake.___child[SIDE_LEFT] = NULL; \
309 ggp = grp = NULL; \
310 par = &fake; \
311 cur = tree->root; \
312 lastdir = SIDE_RGHT; \
313 \
314 for (;;) { \
315 /* Search loop BEGIN */ \
316 if (cur == NULL) { \
317 par->___child[lastdir] = cur = new_node; \
318 cur->___s = lastdir; \
319 cur->___c = COLOR_RED; \
320 cur->___child[SIDE_LEFT] = cur->___child[SIDE_RGHT]; \
321 \
322 if (__isRED(par)) /* red violation */ \
323 ggp->___child[grp->___s] = ROTATE_ARR_NAME(__t_name)[(lastdir << 1)|(par->___s)](grp); \
324 \
325 tree->root = fake.___child[SIDE_RGHT]; \
326 tree->root->___c = COLOR_BLK; \
327 ++(tree->size); \
328 \
329 return (E_OK); \
330 } else if (isRED(lch) && isRED(rch)) { \
331 /* color switch */ \
332 cur->___c = COLOR_RED; \
333 lch->___c = rch->___c = COLOR_BLK; \
334 \
335 if (__isRED(par)) /* red violation */ \
336 ggp->___child[grp->___s] = ROTATE_ARR_NAME(__t_name)[(cur->___s << 1)|(par->___s)](grp); \
337 } else if (__isRED(par) && __isRED(cur)) { \
338 /* red violation */ \
339 ggp->___child[grp->___s] = ROTATE_ARR_NAME(__t_name)[(cur->___s << 1)|(par->___s)](grp); \
340 } \
341 \
342 cmp = RBN_NODECMP_NAME(__t_name) (cur, new_node); \
343 \
344 if (cmp == 0) { \
345 lastdir = cur->___s; \
346 _E(color_t tmp_c = cur->___c;) \
347 _E(NODETYPE(__t_name) *tmp_l = cur->___child[SIDE_LEFT];) \
348 _E(NODETYPE(__t_name) *tmp_r = cur->___child[SIDE_RGHT];) \
349 tree->root = fake.___child[SIDE_RGHT]; \
350 tree->root->___c = COLOR_BLK; \
351 RBN_NODEJOIN_NAME(__t_name) (cur, new_node); \
352 \
353 assert(cur->___s == lastdir); \
354 assert(cur->___c == tmp_c); \
355 assert(cur->___child[SIDE_LEFT] == tmp_l); \
356 assert(cur->___child[SIDE_RGHT] == tmp_r); \
357 \
358 return (E_COLL); \
359 } else if (cmp < 0) { \
360 /* go right */ \
361 PTRMOVE(rch); \
362 lastdir = SIDE_RGHT; \
363 } else { \
364 /* go left */ \
365 PTRMOVE(lch); \
366 lastdir = SIDE_LEFT; \
367 } \
368 } /* Search loop END */ \
369 \
370 abort (); \
371 return (E_FAIL); \
372 }
373
374 #define RBN_SEARCH_CODE(__t_name) \
375 DEF_RBN_SEARCH(__t_name) { \
376 NODETYPE(__t_name) *node; \
377 int cmp; \
378 \
379 node = tree->root; \
380 \
381 while (node != NULL) { \
382 cmp = RBN_NODECMP_NAME(__t_name) (node, k_node); \
383 \
384 if (cmp == 0) \
385 break; \
386 else if (cmp < 0) \
387 node = node->___child[SIDE_RGHT]; \
388 else \
389 node = node->___child[SIDE_LEFT]; \
390 } \
391 \
392 return (node); \
393 }
394
395 #define __WALK_STACK_SIZE 32
396 #define __WALK_STACK_GROW 16
397
398 #define PUSH(n) node_stack[node_stack_count] = (n), ++node_stack_count
399 #define POP(n) (n) = node_stack[--node_stack_count]
400 #define TOP (node_stack[node_stack_count-1])
401 #define CNT node_stack_count
402
403 #define RBN_WALK_CODE(__t_name) \
404 DEF_RBN_WALK(__t_name) { \
405 NODETYPE(__t_name) **node_stack; \
406 register uint16_t node_stack_size; \
407 register uint16_t node_stack_count; \
408 \
409 node_stack_count = 0; \
410 node_stack_size = __WALK_STACK_SIZE; \
411 node_stack = XCALLOC(sizeof (NODETYPE(__t_name) *), node_stack_size); \
412 \
413 PUSH(tree->root); \
414 \
415 switch (order) { \
416 case PREORDER: \
417 while (CNT > 0) { \
418 callback (TOP, cbarg); \
419 if (TOP->___child[SIDE_LEFT] != NULL) { \
420 PUSH(TOP->___child[SIDE_LEFT]); \
421 } else { \
422 __pre: \
423 if (TOP->___child[SIDE_RGHT] != NULL) { \
424 TOP = TOP->___child[SIDE_RGHT]; \
425 } else { \
426 if (--CNT > 0) \
427 goto __pre; \
428 else \
429 break; \
430 } \
431 } \
432 } \
433 break; \
434 case INORDER: \
435 while (CNT > 0) { \
436 if (TOP->___child[SIDE_LEFT] != NULL) { \
437 PUSH(TOP->___child[SIDE_LEFT]); \
438 } else { \
439 __in: \
440 callback (TOP, cbarg); \
441 if (TOP->___child[SIDE_RGHT] != NULL) { \
442 TOP = TOP->___child[SIDE_RGHT]; \
443 } else { \
444 if (--CNT > 0) \
445 goto __in; \
446 else \
447 break; \
448 } \
449 } \
450 } \
451 break; \
452 case POSTORDER: \
453 break; \
454 default: \
455 abort (); \
456 } \
457 XFREE(node_stack); \
458 return; \
459 }
460
461 /*
462 #undef PUSH
463 #undef POP
464 #undef TOP
465 #undef COUNT
466 */
467
468 /*
469 #define RBN_DELETE()
470 #define RBN_REMOVE() RBN_DELETE()
471 */
472
473 /*
474 #define RBN_NODE_LEFT()
475 #define RBN_NODE_RGHT()
476 #define RBN_NODE_RIGHT() RBN_NODE_RGHT()
477 #define RBN_NODE_COLOR()
478 #define RBN_NODE_SIDE()
479 */
480
481 #define RBTREECODE(__t_name) \
482 RBN_CREATE_CODE(__t_name) \
483 RBN_ROTATE_CODE(__t_name); \
484 RBN_NEWNODE_CODE(__t_name) \
485 RBN_SEARCH_CODE(__t_name) \
486 RBN_INSERT_CODE(__t_name) \
487 RBN_WALK_CODE(__t_name) \
488 static const char CONCAT2(__t_name, dummy) = 0
489
490 OSCAP_HIDDEN_END;
491
492 #endif /* REDBLACK_H */