]> mj.ucw.cz Git - libucw.git/blob - lib/redblack.h
Improved and cleaned up the bucket library. The original "single operation
[libucw.git] / lib / redblack.h
1 /*
2  *      Red-black trees
3  *
4  *      (c) 2002, Robert Spalek <robert@ucw.cz>
5  *
6  *      Skeleton based on hash-tables by:
7  *
8  *      (c) 2002, Martin Mares <mj@ucw.cz>
9  *
10  */
11
12 /*
13  * Data structure description:
14  *
15  * A red-black tree is a binary search tree, where records are stored
16  * in nodes (may be also leaves).  Every node has a colour.  The
17  * following restrictions hold:
18  * 
19  * - a parent of a red node is black
20  * - every path from the root to a node with less than 2 children
21  *   contains the same number of black nodes
22  *
23  * A usual interpretation is, that leaves are intervals between records
24  * and contain no data.  Every leaf is black.  This is equivalent, but
25  * saves the space.
26  */
27
28 /*
29  *  This is not a normal header file, it's a generator of red-black trees.
30  *  Each time you include it with parameters set in the corresponding
31  *  preprocessor macros, it generates a tree structure with the parameters
32  *  given.
33  *
34  *  You need to specify:
35  *
36  *  TREE_NODE           data type where a node dwells (usually a struct).
37  *  TREE_PREFIX(x)      macro to add a name prefix (used on all global names
38  *                      defined by the tree generator).
39  *
40  *  Then decide on type of keys:
41  *
42  *  TREE_KEY_ATOMIC=f   use node->f as a key of an atomic type (i.e.,
43  *                      a type which can be compared using '>', `==', and '<')
44  *                      & TREE_ATOMIC_TYPE (defaults to int).
45  *  | TREE_KEY_STRING=f use node->f as a string key, allocated
46  *                      separately from the rest of the node.
47  *  | TREE_KEY_ENDSTRING=f use node->f as a string key, allocated
48  *                      automatically at the end of the node struct
49  *                      (to be declared as "char f[1]" at the end).
50  *  | TREE_KEY_COMPLEX  use a multi-component key; as the name suggests,
51  *                      the passing of parameters is a bit complex then.
52  *                      The TREE_KEY_COMPLEX(x) macro should expand to
53  *                      `x k1, x k2, ... x kn' and you should also define:
54  *    & TREE_KEY_DECL   declaration of function parameters in which key
55  *                      should be passed to all tree operations.
56  *                      That is, `type1 k1, type2 k2, ... typen kn'.
57  *                      With complex keys, TREE_GIVE_CMP is mandatory.
58  *
59  *  Then specify what operations you request (all names are automatically
60  *  prefixed by calling TREE_PREFIX):
61  *
62  *  <always defined>    init() -- initialize the tree.
63  *  TREE_WANT_CLEANUP   cleanup() -- deallocate the tree.
64  *  TREE_WANT_FIND      node *find(key) -- find first node with the specified
65  *                      key, return NULL if no such node exists.
66  *  TREE_WANT_FIND_NEXT node *find_next(node *start) -- find next node with the
67  *                      specified key, return NULL if no such node exists.
68  *                      Implies TREE_DUPLICATES.
69  *  TREE_WANT_SEARCH    node *search(key) -- find the node with the specified
70  *                      or, if it does not exist, the nearest one.
71  *  TREE_WANT_ADJACENT  node *adjacent(node *, uns direction) -- finds next
72  *                      (direction==1) or previous (direction==0) node.
73  *  TREE_WANT_NEW       node *new(key) -- create new node with given key.
74  *                      If it already exists, it is created as the last one.
75  *  TREE_WANT_LOOKUP    node *lookup(key) -- find node with given key,
76  *                      if it doesn't exist, create it. Defining
77  *                      TREE_GIVE_INIT_DATA is strongly recommended.
78  *  TREE_WANT_DELETE    int delete(key) -- delete and deallocate node
79  *                      with a given key. Returns success.
80  *  TREE_WANT_REMOVE    remove(node *) -- delete and deallocate given node.
81  *
82  *  TREE_WANT_DUMP      dump() -- dumps the whole tree to stdout
83  *
84  *  You can also supply several functions:
85  *
86  *  TREE_GIVE_CMP       int cmp(key1, key2) -- return -1, 0, and 1 according to
87  *                      the relation of keys.  By default, we use <, ==, > for
88  *                      atomic types and either strcmp or strcasecmp for
89  *                      strings.
90  *  TREE_GIVE_EXTRA_SIZE int extra_size(key) -- returns how many bytes after the
91  *                      node should be allocated for dynamic data. Default=0
92  *                      or length of the string with TREE_KEY_ENDSTRING.
93  *  TREE_GIVE_INIT_KEY  void init_key(node *,key) -- initialize key in a newly
94  *                      created node. Defaults: assignment for atomic keys
95  *                      and static strings, strcpy for end-allocated strings.
96  *  TREE_GIVE_INIT_DATA void init_data(node *) -- initialize data fields in a
97  *                      newly created node. Very useful for lookup operations.
98  *  TREE_GIVE_ALLOC     void *alloc(unsigned int size) -- allocate space for
99  *                      a node. Default is either normal or pooled allocation
100  *                      depending on whether we want deletions.
101  *                      void free(void *) -- the converse.
102  *
103  *  ... and a couple of extra parameters:
104  *
105  *  TREE_NOCASE         string comparisons should be case-insensitive.
106  *  TREE_ATOMIC_TYPE=t  Atomic values are of type `t' instead of int.
107  *  TREE_USE_POOL=pool  Allocate all nodes from given mempool.
108  *                      Collides with delete/remove functions.
109  *  TREE_GLOBAL         Functions are exported (i.e., not static).
110  *  TREE_CONSERVE_SPACE Use as little space as possible at the price of a
111  *                      little slowdown.
112  *  TREE_DUPLICATES     Records with duplicate keys are allowed.
113  *  TREE_MAX_DEPTH      Maximal depth of a tree (for stack allocation).
114  *
115  *  If you set TREE_WANT_ITERATOR, you also get a iterator macro at no
116  *  extra charge:
117  *
118  *  TREE_FOR_ALL(tree_prefix, tree_pointer, variable)
119  *    {
120  *      // node *variable gets declared automatically
121  *      do_something_with_node(variable);
122  *      // use TREE_BREAK and TREE_CONTINUE instead of break and continue
123  *      // you must not alter contents of the tree here
124  *    }
125  *  TREE_END_FOR;
126  *
127  *  Then include "lib/redblack.h" and voila, you have a tree suiting all your
128  *  needs (at least those which you've revealed :) ).
129  *
130  *  After including this file, all parameter macros are automatically
131  *  undef'd.
132  */
133
134 #include <string.h>
135
136 #if !defined(TREE_NODE) || !defined(TREE_PREFIX)
137 #error Some of the mandatory configuration macros are missing.
138 #endif
139
140 #define P(x) TREE_PREFIX(x)
141
142 /* Declare buckets and the tree.  */
143
144 typedef TREE_NODE P(node);
145
146 #if defined(TREE_WANT_FIND_NEXT) || defined(TREE_WANT_ADJACENT) || defined(TREE_WANT_ITERATOR) || defined(TREE_WANT_REMOVE)
147 #       define TREE_STORE_PARENT
148 #endif
149
150 typedef struct P(bucket) {
151         struct P(bucket) *son[2];
152 #ifdef TREE_STORE_PARENT
153         struct P(bucket) *parent;
154 #endif
155 #if !defined(TREE_CONSERVE_SPACE) && (defined(TREE_GIVE_EXTRA_SIZE) || defined(TREE_KEY_ENDSTRING))
156         uns red_flag:1;
157 #endif
158         P(node) n;
159 #if !defined(TREE_CONSERVE_SPACE) && !defined(TREE_GIVE_EXTRA_SIZE) && !defined(TREE_KEY_ENDSTRING)
160         uns red_flag:1;
161 #endif
162 } P(bucket);
163
164 struct P(tree) {
165         uns count;
166         uns height;                     /* of black nodes */
167         P(bucket) *root;
168 };
169
170 typedef struct P(stack_entry) {
171         P(bucket) *buck;
172         uns son;
173 } P(stack_entry);
174
175 #define T struct P(tree)
176
177 /* Preset parameters */
178
179 #if defined(TREE_KEY_ATOMIC)
180
181 #define TREE_KEY(x) x TREE_KEY_ATOMIC
182
183 #ifndef TREE_ATOMIC_TYPE
184 #       define TREE_ATOMIC_TYPE int
185 #endif
186 #define TREE_KEY_DECL TREE_ATOMIC_TYPE TREE_KEY()
187
188 #ifndef TREE_GIVE_CMP
189 #       define TREE_GIVE_CMP
190         static inline int P(cmp) (TREE_ATOMIC_TYPE x, TREE_ATOMIC_TYPE y)
191         {
192                 if (x < y)
193                         return -1;
194                 else if (x > y)
195                         return 1;
196                 else
197                         return 0;
198         }
199 #endif
200
201 #ifndef TREE_GIVE_INIT_KEY
202 #       define TREE_GIVE_INIT_KEY
203         static inline void P(init_key) (P(node) *n, TREE_ATOMIC_TYPE k)
204         { TREE_KEY(n->) = k; }
205 #endif
206
207 #elif defined(TREE_KEY_STRING) || defined(TREE_KEY_ENDSTRING)
208
209 #ifdef TREE_KEY_STRING
210 #       define TREE_KEY(x) x TREE_KEY_STRING
211 #       ifndef TREE_GIVE_INIT_KEY
212 #               define TREE_GIVE_INIT_KEY
213                 static inline void P(init_key) (P(node) *n, char *k)
214                 { TREE_KEY(n->) = k; }
215 #       endif
216 #else
217 #       define TREE_KEY(x) x TREE_KEY_ENDSTRING
218 #       define TREE_GIVE_EXTRA_SIZE
219         static inline int P(extra_size) (char *k)
220         { return strlen(k); }
221 #       ifndef TREE_GIVE_INIT_KEY
222 #               define TREE_GIVE_INIT_KEY
223                 static inline void P(init_key) (P(node) *n, char *k)
224                 { strcpy(TREE_KEY(n->), k); }
225 #       endif
226 #endif
227 #define TREE_KEY_DECL char *TREE_KEY()
228
229 #ifndef TREE_GIVE_CMP
230 #       define TREE_GIVE_CMP
231         static inline int P(cmp) (char *x, char *y)
232         {
233 #               ifdef TREE_NOCASE
234                         return strcasecmp(x,y);
235 #               else
236                         return strcmp(x,y);
237 #               endif
238         }
239 #endif
240
241 #elif defined(TREE_KEY_COMPLEX)
242
243 #define TREE_KEY(x) TREE_KEY_COMPLEX(x)
244
245 #else
246 #error You forgot to set the tree key type.
247 #endif
248
249 #ifndef TREE_CONSERVE_SPACE
250         static inline uns P(red_flag) (P(bucket) *node)
251         { return node->red_flag; }
252         static inline void P(set_red_flag) (P(bucket) *node, uns flag)
253         { node->red_flag = flag; }
254         static inline P(bucket) * P(tree_son) (P(bucket) *node, uns id)
255         { return node->son[id]; }
256         static inline void P(set_tree_son) (P(bucket) *node, uns id, P(bucket) *son)
257         { node->son[id] = son; }
258 #else
259         /* Pointers are aligned, hence we can use lower bits.  */
260         static inline uns P(red_flag) (P(bucket) *node)
261         { return ((addr_int_t) node->son[0]) & 1L; }
262         static inline void P(set_red_flag) (P(bucket) *node, uns flag)
263         { (addr_int_t) node->son[0] = (((addr_int_t) node->son[0]) & ~1L) | (flag & 1L); }
264         static inline P(bucket) * P(tree_son) (P(bucket) *node, uns id)
265         { return (void *) (((addr_int_t) node->son[id]) & ~1L); }
266         static inline void P(set_tree_son) (P(bucket) *node, uns id, P(bucket) *son)
267         { node->son[id] = (void *) ((addr_int_t) son | (((addr_int_t) node->son[id]) & 1L) ); }
268 #endif
269
270 /* Defaults for missing parameters.  */
271
272 #ifndef TREE_GIVE_CMP
273 #error Unable to determine how to compare two keys.
274 #endif
275
276 #ifdef TREE_GIVE_EXTRA_SIZE
277 /* This trickery is needed to avoid `unused parameter' warnings */
278 #       define TREE_EXTRA_SIZE P(extra_size)
279 #else
280 /*
281  *  Beware, C macros are expanded iteratively, not recursively,
282  *  hence we get only a _single_ argument, although the expansion
283  *  of TREE_KEY contains commas.
284  */
285 #       define TREE_EXTRA_SIZE(x) 0
286 #endif
287
288 #ifndef TREE_GIVE_INIT_KEY
289 #       error Unable to determine how to initialize keys.
290 #endif
291
292 #ifndef TREE_GIVE_INIT_DATA
293 static inline void P(init_data) (P(node) *n UNUSED)
294 {
295 }
296 #endif
297
298 #include <stdlib.h>
299
300 #ifndef TREE_GIVE_ALLOC
301 #       ifdef TREE_USE_POOL
302                 static inline void * P(alloc) (unsigned int size)
303                 { return mp_alloc_fast(TREE_USE_POOL, size); }
304 #               define TREE_SAFE_FREE(x)
305 #       else
306                 static inline void * P(alloc) (unsigned int size)
307                 { return xmalloc(size); }
308
309                 static inline void P(free) (void *x)
310                 { xfree(x); }
311 #       endif
312 #endif
313
314 #ifndef TREE_SAFE_FREE
315 #       define TREE_SAFE_FREE(x)        P(free) (x)
316 #endif
317
318 #ifdef TREE_GLOBAL
319 #       define STATIC
320 #else
321 #       define STATIC static
322 #endif
323
324 #ifndef TREE_MAX_DEPTH
325 #       define TREE_MAX_DEPTH 64
326 #endif
327
328 #if defined(TREE_WANT_FIND_NEXT) && !defined(TREE_DUPLICATES)
329 #       define TREE_DUPLICATES
330 #endif
331
332 #ifdef TREE_WANT_LOOKUP
333 #ifndef TREE_WANT_FIND
334 #       define TREE_WANT_FIND
335 #endif
336 #ifndef TREE_WANT_NEW
337 #       define TREE_WANT_NEW
338 #endif
339 #endif
340
341 /* Now the operations */
342
343 STATIC void P(init) (T *t)
344 {
345         t->count = t->height = 0;
346         t->root = NULL;
347 }
348
349 #ifdef TREE_WANT_CLEANUP
350 static void P(cleanup_subtree) (T *t, P(bucket) *node)
351 {
352         if (!node)
353                 return;
354         P(cleanup_subtree) (t, P(tree_son) (node, 0));
355         P(cleanup_subtree) (t, P(tree_son) (node, 1));
356         P(free) (node);
357         t->count--;
358 }
359
360 STATIC void P(cleanup) (T *t)
361 {
362         P(cleanup_subtree) (t, t->root);
363         ASSERT(!t->count);
364         t->height = 0;
365 }
366 #endif
367
368 static uns P(fill_stack) (P(stack_entry) *stack, uns max_depth, P(bucket) *node, TREE_KEY_DECL, uns son_id UNUSED)
369 {
370         uns i;
371         stack[0].buck = node;
372         for (i=0; stack[i].buck; i++)
373         {
374                 int cmp;
375                 cmp = P(cmp) (TREE_KEY(), TREE_KEY(stack[i].buck->n.));
376                 if (cmp == 0)
377                         break;
378                 else if (cmp < 0)
379                         stack[i].son = 0;
380                 else
381                         stack[i].son = 1;
382                 ASSERT(i+1 < max_depth);
383                 stack[i+1].buck = P(tree_son) (stack[i].buck, stack[i].son);
384         }
385 #ifdef TREE_DUPLICATES
386         if (stack[i].buck)
387         {
388                 uns idx;
389                 /* Find first/last of equal keys according to son_id.  */
390                 idx = P(fill_stack) (stack+i+1, max_depth-i-1,
391                         P(tree_son) (stack[i].buck, son_id), TREE_KEY(), son_id);
392                 if (stack[i+1+idx].buck)
393                 {
394                         stack[i].son = son_id;
395                         i = i+1+idx;
396                 }
397         }
398 #endif
399         stack[i].son = 10;
400         return i;
401 }
402
403 #ifdef TREE_WANT_FIND
404 STATIC P(node) * P(find) (T *t, TREE_KEY_DECL)
405 {
406         P(stack_entry) stack[TREE_MAX_DEPTH];
407         uns depth;
408         depth = P(fill_stack) (stack, TREE_MAX_DEPTH, t->root, TREE_KEY(), 0);
409         return stack[depth].buck ? &stack[depth].buck->n : NULL;
410 }
411 #endif
412
413 #ifdef TREE_STORE_PARENT
414 STATIC P(node) * P(adjacent) (P(node) *start, uns direction)
415 {
416         P(bucket) *node = SKIP_BACK(P(bucket), n, start);
417         P(bucket) *next = P(tree_son) (node, direction);
418         if (next)
419         {
420                 while (1)
421                 {
422                         node = P(tree_son) (next, 1 - direction);
423                         if (!node)
424                                 break;
425                         next = node;
426                 }
427         }
428         else
429         {
430                 next = node->parent;
431                 while (next && node == P(tree_son) (next, direction))
432                 {
433                         node = next;
434                         next = node->parent;
435                 }
436                 if (!next)
437                         return NULL;
438                 ASSERT(node == P(tree_son) (next, 1 - direction));
439         }
440         return &next->n;
441 }
442 #endif
443
444 #if defined(TREE_DUPLICATES) || defined(TREE_WANT_DELETE) || defined(TREE_WANT_REMOVE)
445 static int P(find_next_node) (P(stack_entry) *stack, uns max_depth, uns direction)
446 {
447         uns depth = 0;
448         if (stack[0].buck)
449         {
450                 ASSERT(depth+1 < max_depth);
451                 stack[depth].son = direction;
452                 stack[depth+1].buck = P(tree_son) (stack[depth].buck, direction);
453                 depth++;
454                 while (stack[depth].buck)
455                 {
456                         ASSERT(depth+1 < max_depth);
457                         stack[depth].son = 1 - direction;
458                         stack[depth+1].buck = P(tree_son) (stack[depth].buck, 1 - direction);
459                         depth++;
460                 }
461         }
462         return depth;
463 }
464 #endif
465
466 #ifdef TREE_WANT_FIND_NEXT
467 STATIC P(node) * P(find_next) (P(node) *start)
468 {
469         P(node) *next = P(adjacent) (start, 1);
470         if (next && P(cmp) (TREE_KEY(start->), TREE_KEY(next->)) == 0)
471                 return next;
472         else
473                 return NULL;
474
475 }
476 #endif
477
478 #ifdef TREE_WANT_SEARCH
479 STATIC P(node) * P(search) (T *t, TREE_KEY_DECL)
480 {
481         P(stack_entry) stack[TREE_MAX_DEPTH];
482         uns depth;
483         depth = P(fill_stack) (stack, TREE_MAX_DEPTH, t->root, TREE_KEY(), 0);
484         if (!stack[depth].buck)
485         {
486                 if (depth > 0)
487                         depth--;
488                 else
489                         return NULL;
490         }
491         return &stack[depth].buck->n;
492 }
493 #endif
494
495 #if 0
496 #define TREE_TRACE(txt...) do { printf(txt); fflush(stdout); } while (0)
497 #else
498 #define TREE_TRACE(txt...)
499 #endif
500
501 static inline P(bucket) * P(rotation) (P(bucket) *node, uns son_id)
502 {
503         /* Destroys red_flag's in node, son.  Returns new root.  */
504         P(bucket) *son = P(tree_son) (node, son_id);
505         TREE_TRACE("Rotation (node %d, son %d), direction %d\n", node->n.key, son->n.key, son_id);
506         node->son[son_id] = P(tree_son) (son, 1-son_id);
507         son->son[1-son_id] = node;
508 #ifdef TREE_STORE_PARENT
509         if (node->son[son_id])
510                 node->son[son_id]->parent = node;
511         son->parent = node->parent;
512         node->parent = son;
513 #endif
514         return son;
515 }
516
517 static void P(rotate_after_insert) (T *t, P(stack_entry) *stack, uns depth)
518 {
519         P(bucket) *node;
520         P(bucket) *parent, *grand, *uncle;
521         int s1, s2;
522 try_it_again:
523         node = stack[depth].buck;
524         ASSERT(P(red_flag) (node));
525         /* At this moment, node became red.  The paths sum have
526          * been preserved, but we have to check the parental
527          * condition.  */
528         if (depth == 0)
529         {
530                 ASSERT(t->root == node);
531                 return;
532         }
533         parent = stack[depth-1].buck;
534         if (!P(red_flag) (parent))
535                 return;
536         if (depth == 1)
537         {
538                 ASSERT(t->root == parent);
539                 P(set_red_flag) (parent, 0);
540                 t->height++;
541                 return;
542         }
543         grand = stack[depth-2].buck;
544         ASSERT(!P(red_flag) (grand));
545         /* The parent is also red, the grandparent exists and it
546          * is black.  */
547         s1 = stack[depth-1].son;
548         s2 = stack[depth-2].son;
549         uncle = P(tree_son) (grand, 1-s2);
550         if (uncle && P(red_flag) (uncle))
551         {
552                 /* Red parent and uncle, black grandparent.
553                  * Exchange and try another iteration. */
554                 P(set_red_flag) (parent, 0);
555                 P(set_red_flag) (uncle, 0);
556                 P(set_red_flag) (grand, 1);
557                 depth -= 2;
558                 TREE_TRACE("Swapping colours (parent %d, uncle %d, grand %d), passing thru\n", parent->n.key, uncle->n.key, grand->n.key);
559                 goto try_it_again;
560         }
561         /* Black uncle and grandparent, we need to rotate.  Test
562          * the direction.  */
563         if (s1 == s2)
564         {
565                 node = P(rotation) (grand, s2);
566                 P(set_red_flag) (parent, 0);
567                 P(set_red_flag) (grand, 1);
568         }
569         else
570         {
571                 grand->son[s2] = P(rotation) (parent, s1);
572                 node = P(rotation) (grand, s2);
573                 P(set_red_flag) (grand, 1);
574                 P(set_red_flag) (parent, 1);
575                 P(set_red_flag) (node, 0);
576         }
577         if (depth >= 3)
578                 P(set_tree_son) (stack[depth-3].buck, stack[depth-3].son, node);
579         else
580                 t->root = node;
581 }
582
583 #ifdef TREE_WANT_NEW
584 STATIC P(node) * P(new) (T *t, TREE_KEY_DECL)
585 {
586         P(stack_entry) stack[TREE_MAX_DEPTH];
587         P(bucket) *added;
588         uns depth;
589         depth = P(fill_stack) (stack, TREE_MAX_DEPTH, t->root, TREE_KEY(), 1);
590 #ifdef TREE_DUPLICATES
591         /* It is the last found value, hence everything in the right subtree is
592          * strongly _bigger_.  */
593         depth += P(find_next_node) (stack+depth, TREE_MAX_DEPTH-depth, 1);
594 #endif
595         ASSERT(!stack[depth].buck);
596         /* We are in a leaf, hence we can easily append a new leaf to it.  */
597         added = P(alloc) (sizeof(struct P(bucket)) + TREE_EXTRA_SIZE(TREE_KEY()) );
598         added->son[0] = added->son[1] = NULL;
599         stack[depth].buck = added;
600         if (depth > 0)
601         {
602 #ifdef TREE_STORE_PARENT
603                 added->parent = stack[depth-1].buck;
604 #endif
605                 P(set_tree_son) (stack[depth-1].buck, stack[depth-1].son, added);
606         }
607         else
608         {
609 #ifdef TREE_STORE_PARENT
610                 added->parent = NULL;
611 #endif
612                 t->root = added;
613         }
614         P(set_red_flag) (added, 1);     /* Set it red to not disturb the path sum.  */
615         P(init_key) (&added->n, TREE_KEY());
616         P(init_data) (&added->n);
617         t->count++;
618         /* Let us reorganize the red_flag's and the structure of the tree.  */
619         P(rotate_after_insert) (t, stack, depth);
620         return &added->n;
621 }
622 #endif
623
624 #ifdef TREE_WANT_LOOKUP
625 STATIC P(node) * P(lookup) (T *t, TREE_KEY_DECL)
626 {
627         P(node) *node;
628         node = P(find) (t, TREE_KEY());
629         if (node)
630                 return node;
631         return P(new) (t, TREE_KEY());
632 }
633 #endif
634
635 #if defined(TREE_WANT_REMOVE) || defined(TREE_WANT_DELETE)
636 static void P(rotate_after_delete) (T *t, P(stack_entry) *stack, int depth)
637 {
638         uns iteration = 0;
639         P(bucket) *parent, *sibling, *instead;
640         uns parent_red, del_son, sibl_red;
641 missing_black:
642         if (depth < 0)
643         {
644                 t->height--;
645                 return;
646         }
647         parent = stack[depth].buck;
648         parent_red = P(red_flag) (parent);
649         del_son = stack[depth].son;
650         /* For the 1st iteration: we have deleted parent->son[del_son], which
651          * was a black node with no son.  Hence there is one mising black
652          * vertex in that path, which we are going to fix now.
653          *
654          * For other iterations: in that path, there is also missing a black
655          * node.  */
656         if (!iteration)
657                 ASSERT(!P(tree_son) (parent, del_son));
658         sibling = P(tree_son) (parent, 1-del_son);
659         ASSERT(sibling);
660         sibl_red = P(red_flag) (sibling);
661         instead = NULL;
662         if (!sibl_red)
663         {
664                 P(bucket) *son[2];
665                 uns red[2];
666                 son[0] = P(tree_son) (sibling, 0);
667                 son[1] = P(tree_son) (sibling, 1);
668                 red[0] = son[0] ? P(red_flag) (son[0]) : 0;
669                 red[1] = son[1] ? P(red_flag) (son[1]) : 0;
670                 if (!red[0] && !red[1])
671                 {
672                         P(set_red_flag) (sibling, 1);
673                         P(set_red_flag) (parent, 0);
674                         if (parent_red)
675                                 return;
676                         else
677                         {
678                                 depth--;
679                                 iteration++;
680                                 TREE_TRACE("Swapping colours (parent %d, sibling %d), passing thru\n", parent->n.key, sibling->n.key);
681                                 goto missing_black;
682                         }
683                 } else if (!red[del_son])
684                 {
685                         instead = P(rotation) (parent, 1-del_son);
686                         P(set_red_flag) (instead, parent_red);
687                         P(set_red_flag) (parent, 0);
688                         P(set_red_flag) (son[1-del_son], 0);
689                 } else /* red[del_son] */
690                 {
691                         parent->son[1-del_son] = P(rotation) (sibling, del_son);
692                         instead = P(rotation) (parent, 1-del_son);
693                         P(set_red_flag) (instead, parent_red);
694                         P(set_red_flag) (parent, 0);
695                         P(set_red_flag) (sibling, 0);
696                 }
697         } else /* sibl_red */
698         {
699                 P(bucket) *grand[2], *son;
700                 uns red[2];
701                 ASSERT(!parent_red);
702                 son = P(tree_son) (sibling, del_son);
703                 ASSERT(son && !P(red_flag) (son));
704                 grand[0] = P(tree_son) (son, 0);
705                 grand[1] = P(tree_son) (son, 1);
706                 red[0] = grand[0] ? P(red_flag) (grand[0]) : 0;
707                 red[1] = grand[1] ? P(red_flag) (grand[1]) : 0;
708                 if (!red[0] && !red[1])
709                 {
710                         instead = P(rotation) (parent, 1-del_son);
711                         P(set_red_flag) (instead, 0);
712                         P(set_red_flag) (parent, 0);
713                         P(set_red_flag) (son, 1);
714                 }
715                 else if (!red[del_son])
716                 {
717                         parent->son[1-del_son] = P(rotation) (sibling, del_son);
718                         instead = P(rotation) (parent, 1-del_son);
719                         P(set_red_flag) (instead, 0);
720                         P(set_red_flag) (parent, 0);
721                         P(set_red_flag) (sibling, 1);
722                         P(set_red_flag) (grand[1-del_son], 0);
723                 } else /* red[del_son] */
724                 {
725                         sibling->son[del_son] = P(rotation) (son, del_son);
726                         parent->son[1-del_son] = P(rotation) (sibling, del_son);
727                         instead = P(rotation) (parent, 1-del_son);
728                         P(set_red_flag) (instead, 0);
729                         P(set_red_flag) (parent, 0);
730                         P(set_red_flag) (sibling, 1);
731                         P(set_red_flag) (son, 0);
732                 }
733         }
734         /* We have performed all desired rotations and need to store the new
735          * pointer to the subtree.  */
736         ASSERT(instead);
737         if (depth > 0)
738                 P(set_tree_son) (stack[depth-1].buck, stack[depth-1].son, instead);
739         else
740                 t->root = instead;
741 }
742
743 static void P(remove_by_stack) (T *t, P(stack_entry) *stack, uns depth)
744 {
745         P(bucket) *node = stack[depth].buck;
746         P(bucket) *son;
747         uns i;
748         for (i=0; i<depth; i++)
749                 ASSERT(P(tree_son) (stack[i].buck, stack[i].son) == stack[i+1].buck);
750         if (P(tree_son) (node, 0) && P(tree_son) (node, 1))
751         {
752                 P(bucket) *xchg;
753                 uns flag_node, flag_xchg;
754                 uns d = P(find_next_node) (stack+depth, TREE_MAX_DEPTH-depth, 1);
755
756                 ASSERT(d >= 2);
757                 d--;
758                 xchg = stack[depth+d].buck;
759                 flag_node = P(red_flag) (node);
760                 flag_xchg = P(red_flag) (xchg);
761                 ASSERT(!P(tree_son) (xchg, 0));
762                 son = P(tree_son) (xchg, 1);
763                 stack[depth].buck = xchg;       /* Magic iff d == 1.  */
764                 stack[depth+d].buck = node;
765                 xchg->son[0] = P(tree_son) (node, 0);
766                 xchg->son[1] = P(tree_son) (node, 1);
767                 if (depth > 0)
768                         P(set_tree_son) (stack[depth-1].buck, stack[depth-1].son, xchg);
769                 else
770                         t->root = xchg;
771                 node->son[0] = NULL;
772                 node->son[1] = son;
773                 P(set_tree_son) (stack[depth+d-1].buck, stack[depth+d-1].son, node);
774 #ifdef TREE_STORE_PARENT
775                 xchg->parent = depth > 0 ? stack[depth-1].buck : NULL;
776                 xchg->son[0]->parent = xchg;
777                 xchg->son[1]->parent = xchg;
778                 node->parent = stack[depth+d-1].buck;
779                 if (son)
780                         son->parent = node;
781 #endif
782                 P(set_red_flag) (xchg, flag_node);
783                 P(set_red_flag) (node, flag_xchg);
784                 depth += d;
785         }
786         else if (P(tree_son) (node, 0))
787                 son = P(tree_son) (node, 0);
788         else
789                 son = P(tree_son) (node, 1);
790         /* At this moment, stack[depth].buck == node and it has at most one son
791          * and it is stored in the variable son.  */
792         t->count--;
793         if (depth > 0)
794         {
795                 P(set_tree_son) (stack[depth-1].buck, stack[depth-1].son, son);
796 #ifdef TREE_STORE_PARENT
797                 if (son)
798                         son->parent = stack[depth-1].buck;
799 #endif
800         }
801         else
802         {
803                 t->root = son;
804 #ifdef TREE_STORE_PARENT
805                 if (son)
806                         son->parent = NULL;
807 #endif
808         }
809         if (P(red_flag) (node))
810         {
811                 ASSERT(!son);
812                 return;
813         }
814         TREE_SAFE_FREE(node);
815         /* We have deleted a black node.  */
816         if (son)
817         {
818                 ASSERT(P(red_flag) (son));
819                 P(set_red_flag) (son, 0);
820                 return;
821         }
822         P(rotate_after_delete) (t, stack, (int) depth - 1);
823 }
824 #endif
825
826 #ifdef TREE_WANT_REMOVE
827 STATIC void P(remove) (T *t, P(node) *Node)
828 {
829         P(stack_entry) stack[TREE_MAX_DEPTH];
830         P(bucket) *node = SKIP_BACK(P(bucket), n, Node);
831         uns depth = 0, i;
832         stack[0].buck = node;
833         stack[0].son = 10;
834         while (node->parent)
835         {
836                 depth++;
837                 ASSERT(depth < TREE_MAX_DEPTH);
838                 stack[depth].buck = node->parent;
839                 stack[depth].son = P(tree_son) (node->parent, 0) == node ? 0 : 1;
840                 node = node->parent;
841         }
842         for (i=0; i<(depth+1)/2; i++)
843         {
844                 P(stack_entry) tmp = stack[i];
845                 stack[i] = stack[depth-i];
846                 stack[depth-i] = tmp;
847         }
848         P(remove_by_stack) (t, stack, depth);
849 }
850 #endif
851
852 #ifdef TREE_WANT_DELETE
853 STATIC int P(delete) (T *t, TREE_KEY_DECL)
854 {
855         P(stack_entry) stack[TREE_MAX_DEPTH];
856         uns depth;
857         depth = P(fill_stack) (stack, TREE_MAX_DEPTH, t->root, TREE_KEY(), 1);
858         if (stack[depth].buck)
859         {
860                 P(remove_by_stack) (t, stack, depth);
861                 return 1;
862         }
863         else
864                 return 0;
865 }
866 #endif
867
868 #ifdef TREE_WANT_DUMP
869 static void P(dump_subtree) (struct fastbuf *fb, T *t, P(bucket) *node, P(bucket) *parent, int cmp_res, int level, uns black)
870 {
871         uns flag;
872         int i;
873         if (!node)
874         {
875                 ASSERT(black == t->height);
876                 return;
877         }
878         flag = P(red_flag) (node);
879 #ifdef TREE_STORE_PARENT
880         ASSERT(node->parent == parent);
881 #endif
882         if (parent)
883         {
884                 ASSERT(!flag || !P(red_flag) (parent));
885                 cmp_res *= P(cmp) (TREE_KEY(node->n.), TREE_KEY(parent->n.));
886 #ifdef TREE_DUPLICATES
887                 ASSERT(cmp_res >= 0);
888 #else
889                 ASSERT(cmp_res > 0);
890 #endif
891         }
892         P(dump_subtree) (fb, t, P(tree_son) (node, 0), node, -1, level+1, black + (1-flag));
893         if (fb)
894         {
895                 char tmp[20];
896                 for (i=0; i<level; i++)
897                         bputs(fb, "  ");
898                 sprintf(tmp, "L%d %c\t", level, flag ? 'R' : 'B');
899                 bputs(fb, tmp);
900                 P(dump_key) (fb, &node->n);
901                 P(dump_data) (fb, &node->n);
902                 bputs(fb, "\n");
903         }
904         P(dump_subtree) (fb, t, P(tree_son) (node, 1), node, +1, level+1, black + (1-flag));
905 }
906
907 STATIC void P(dump) (struct fastbuf *fb, T *t)
908 {
909         if (fb)
910         {
911                 char tmp[50];
912                 sprintf(tmp, "Tree of %d nodes and height %d\n", t->count, t->height);
913                 bputs(fb, tmp);
914         }
915         P(dump_subtree) (fb, t, t->root, NULL, 0, 0, 0);
916         if (fb)
917         {
918                 bputs(fb, "\n");
919                 bflush(fb);
920         }
921 }
922 #endif
923
924 /* And the iterator */
925
926 #ifdef TREE_WANT_ITERATOR
927 static P(node) * P(first_node) (T *t, uns direction)
928 {
929         P(bucket) *node = t->root, *prev = NULL;
930         while (node)
931         {
932                 prev = node;
933                 node = P(tree_son) (node, direction);
934         }
935         return prev ? &prev->n : NULL;
936 }
937
938 #ifndef TREE_FOR_ALL
939
940 #define TREE_FOR_ALL(t_px, t_ptr, t_var)                                                \
941 do                                                                                      \
942 {                                                                                       \
943         TREE_GLUE(t_px,node) *t_var = TREE_GLUE(t_px,first_node)(t_ptr, 0);             \
944         for (; t_var; t_var = TREE_GLUE(t_px,adjacent)(t_var, 1))                       \
945         {
946 #define TREE_END_FOR } } while(0)
947 #define TREE_BREAK break
948 #define TREE_CONTINUE continue
949 #define TREE_GLUE(x,y) x##_##y
950
951 #endif
952 #endif
953
954 /* Finally, undefine all the parameters */
955
956 #undef P
957 #undef T
958
959 #undef TREE_NODE
960 #undef TREE_PREFIX
961 #undef TREE_KEY_ATOMIC
962 #undef TREE_KEY_STRING
963 #undef TREE_KEY_ENDSTRING
964 #undef TREE_KEY_COMPLEX
965 #undef TREE_KEY_DECL
966 #undef TREE_WANT_CLEANUP
967 #undef TREE_WANT_FIND
968 #undef TREE_WANT_FIND_NEXT
969 #undef TREE_WANT_SEARCH
970 #undef TREE_WANT_ADJACENT
971 #undef TREE_WANT_NEW
972 #undef TREE_WANT_LOOKUP
973 #undef TREE_WANT_DELETE
974 #undef TREE_WANT_REMOVE
975 #undef TREE_WANT_DUMP
976 #undef TREE_WANT_ITERATOR
977 #undef TREE_GIVE_CMP
978 #undef TREE_GIVE_EXTRA_SIZE
979 #undef TREE_GIVE_INIT_KEY
980 #undef TREE_GIVE_INIT_DATA
981 #undef TREE_GIVE_ALLOC
982 #undef TREE_NOCASE
983 #undef TREE_ATOMIC_TYPE
984 #undef TREE_USE_POOL
985 #undef TREE_STATIC
986 #undef TREE_CONSERVE_SPACE
987 #undef TREE_DUPLICATES
988 #undef TREE_MAX_DEPTH
989 #undef TREE_STORE_PARENT
990 #undef TREE_KEY
991 #undef TREE_EXTRA_SIZE
992 #undef TREE_SAFE_FREE
993 #undef TREE_TRACE
994 #undef STATIC