warnings: fix compilation with old autoconf
[gnulib/ericb.git] / lib / gl_anyrbtree_list2.h
bloba90d16e948aba3feb1ce20aa7c18a65d08bdadf4
1 /* Sequential list data type implemented by a binary tree.
2 Copyright (C) 2006-2007, 2009-2017 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Common code of gl_rbtree_list.c and gl_rbtreehash_list.c. */
20 /* -------------------------- gl_list_t Data Type -------------------------- */
22 /* Create a subtree for count >= 1 elements.
23 Its black-height bh is passed as argument, with
24 2^bh - 1 <= count <= 2^(bh+1) - 1. bh == 0 implies count == 1.
25 Its height is h where 2^(h-1) <= count <= 2^h - 1.
26 Return NULL upon out-of-memory. */
27 static gl_list_node_t
28 create_subtree_with_contents (unsigned int bh,
29 size_t count, const void **contents)
31 size_t half1 = (count - 1) / 2;
32 size_t half2 = count / 2;
33 /* Note: half1 + half2 = count - 1. */
34 gl_list_node_t node =
35 (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl));
36 if (node == NULL)
37 return NULL;
39 if (half1 > 0)
41 /* half1 > 0 implies count > 1, implies bh >= 1, implies
42 2^(bh-1) - 1 <= half1 <= 2^bh - 1. */
43 node->left =
44 create_subtree_with_contents (bh - 1, half1, contents);
45 if (node->left == NULL)
46 goto fail1;
47 node->left->parent = node;
49 else
50 node->left = NULL;
52 node->value = contents[half1];
54 if (half2 > 0)
56 /* half2 > 0 implies count > 1, implies bh >= 1, implies
57 2^(bh-1) - 1 <= half2 <= 2^bh - 1. */
58 node->right =
59 create_subtree_with_contents (bh - 1, half2, contents + half1 + 1);
60 if (node->right == NULL)
61 goto fail2;
62 node->right->parent = node;
64 else
65 node->right = NULL;
67 node->color = (bh == 0 ? RED : BLACK);
69 node->branch_size = count;
71 return node;
73 fail2:
74 if (node->left != NULL)
75 free_subtree (node->left);
76 fail1:
77 free (node);
78 return NULL;
81 static gl_list_t
82 gl_tree_nx_create (gl_list_implementation_t implementation,
83 gl_listelement_equals_fn equals_fn,
84 gl_listelement_hashcode_fn hashcode_fn,
85 gl_listelement_dispose_fn dispose_fn,
86 bool allow_duplicates,
87 size_t count, const void **contents)
89 struct gl_list_impl *list =
90 (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl));
92 if (list == NULL)
93 return NULL;
95 list->base.vtable = implementation;
96 list->base.equals_fn = equals_fn;
97 list->base.hashcode_fn = hashcode_fn;
98 list->base.dispose_fn = dispose_fn;
99 list->base.allow_duplicates = allow_duplicates;
100 #if WITH_HASHTABLE
102 size_t estimate = xsum (count, count / 2); /* 1.5 * count */
103 if (estimate < 10)
104 estimate = 10;
105 list->table_size = next_prime (estimate);
106 if (size_overflow_p (xtimes (list->table_size, sizeof (gl_hash_entry_t))))
107 goto fail1;
108 list->table =
109 (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t));
110 if (list->table == NULL)
111 goto fail1;
113 #endif
114 if (count > 0)
116 /* Assuming 2^bh - 1 <= count <= 2^(bh+1) - 2, we create a tree whose
117 upper bh levels are black, and only the partially present lowest
118 level is red. */
119 unsigned int bh;
121 size_t n;
122 for (n = count + 1, bh = 0; n > 1; n = n >> 1)
123 bh++;
126 list->root = create_subtree_with_contents (bh, count, contents);
127 if (list->root == NULL)
128 goto fail2;
129 list->root->parent = NULL;
131 #if WITH_HASHTABLE
132 /* Now that the tree is built, node_position() works. Now we can
133 add the nodes to the hash table. */
134 if (add_nodes_to_buckets (list) < 0)
135 goto fail3;
136 #endif
138 else
139 list->root = NULL;
141 return list;
143 #if WITH_HASHTABLE
144 fail3:
145 free_subtree (list->root);
146 #endif
147 fail2:
148 #if WITH_HASHTABLE
149 free (list->table);
150 fail1:
151 #endif
152 free (list);
153 return NULL;
156 /* Rotate left a subtree.
159 / \ / \
160 A D --> B E
161 / \ / \
162 C E A C
164 Change the tree structure, update the branch sizes.
165 The caller must update the colors and register D as child of its parent. */
166 static gl_list_node_t
167 rotate_left (gl_list_node_t b_node, gl_list_node_t d_node)
169 gl_list_node_t a_node = b_node->left;
170 gl_list_node_t c_node = d_node->left;
171 gl_list_node_t e_node = d_node->right;
173 b_node->right = c_node;
174 d_node->left = b_node;
176 d_node->parent = b_node->parent;
177 b_node->parent = d_node;
178 if (c_node != NULL)
179 c_node->parent = b_node;
181 b_node->branch_size =
182 (a_node != NULL ? a_node->branch_size : 0)
183 + 1 + (c_node != NULL ? c_node->branch_size : 0);
184 d_node->branch_size =
185 b_node->branch_size + 1 + (e_node != NULL ? e_node->branch_size : 0);
187 return d_node;
190 /* Rotate right a subtree.
193 / \ / \
194 B E --> A D
195 / \ / \
196 A C C E
198 Change the tree structure, update the branch sizes.
199 The caller must update the colors and register B as child of its parent. */
200 static gl_list_node_t
201 rotate_right (gl_list_node_t b_node, gl_list_node_t d_node)
203 gl_list_node_t a_node = b_node->left;
204 gl_list_node_t c_node = b_node->right;
205 gl_list_node_t e_node = d_node->right;
207 d_node->left = c_node;
208 b_node->right = d_node;
210 b_node->parent = d_node->parent;
211 d_node->parent = b_node;
212 if (c_node != NULL)
213 c_node->parent = d_node;
215 d_node->branch_size =
216 (c_node != NULL ? c_node->branch_size : 0)
217 + 1 + (e_node != NULL ? e_node->branch_size : 0);
218 b_node->branch_size =
219 (a_node != NULL ? a_node->branch_size : 0) + 1 + d_node->branch_size;
221 return b_node;
224 /* Ensure the tree is balanced, after an insertion operation.
225 Also assigns node->color.
226 parent is the given node's parent, known to be non-NULL. */
227 static void
228 rebalance_after_add (gl_list_t list, gl_list_node_t node, gl_list_node_t parent)
230 for (;;)
232 /* At this point, parent = node->parent != NULL.
233 Think of node->color being RED (although node->color is not yet
234 assigned.) */
235 gl_list_node_t grandparent;
236 gl_list_node_t uncle;
238 if (parent->color == BLACK)
240 /* A RED color for node is acceptable. */
241 node->color = RED;
242 return;
245 grandparent = parent->parent;
246 /* Since parent is RED, we know that
247 grandparent is != NULL and colored BLACK. */
249 if (grandparent->left == parent)
250 uncle = grandparent->right;
251 else if (grandparent->right == parent)
252 uncle = grandparent->left;
253 else
254 abort ();
256 if (uncle != NULL && uncle->color == RED)
258 /* Change grandparent from BLACK to RED, and
259 change parent and uncle from RED to BLACK.
260 This makes it acceptable for node to be RED. */
261 node->color = RED;
262 parent->color = uncle->color = BLACK;
263 node = grandparent;
265 else
267 /* grandparent and uncle are BLACK. parent is RED. node wants
268 to be RED too.
269 In this case, recoloring is not sufficient. Need to perform
270 one or two rotations. */
271 gl_list_node_t *grandparentp;
273 if (grandparent->parent == NULL)
274 grandparentp = &list->root;
275 else if (grandparent->parent->left == grandparent)
276 grandparentp = &grandparent->parent->left;
277 else if (grandparent->parent->right == grandparent)
278 grandparentp = &grandparent->parent->right;
279 else
280 abort ();
282 if (grandparent->left == parent)
284 if (parent->right == node)
286 /* Rotation between node and parent. */
287 grandparent->left = rotate_left (parent, node);
288 node = parent;
289 parent = grandparent->left;
291 /* grandparent and uncle are BLACK. parent and node want to be
292 RED. parent = grandparent->left. node = parent->left.
294 grandparent parent
295 bh+1 bh+1
296 / \ / \
297 parent uncle --> node grandparent
298 bh bh bh bh
299 / \ / \
300 node C C uncle
301 bh bh bh bh
303 *grandparentp = rotate_right (parent, grandparent);
304 parent->color = BLACK;
305 node->color = grandparent->color = RED;
307 else /* grandparent->right == parent */
309 if (parent->left == node)
311 /* Rotation between node and parent. */
312 grandparent->right = rotate_right (node, parent);
313 node = parent;
314 parent = grandparent->right;
316 /* grandparent and uncle are BLACK. parent and node want to be
317 RED. parent = grandparent->right. node = parent->right.
319 grandparent parent
320 bh+1 bh+1
321 / \ / \
322 uncle parent --> grandparent node
323 bh bh bh bh
324 / \ / \
325 C node uncle C
326 bh bh bh bh
328 *grandparentp = rotate_left (grandparent, parent);
329 parent->color = BLACK;
330 node->color = grandparent->color = RED;
332 return;
335 /* Start again with a new (node, parent) pair. */
336 parent = node->parent;
338 if (parent == NULL)
340 /* Change node's color from RED to BLACK. This increases the
341 tree's black-height. */
342 node->color = BLACK;
343 return;
348 /* Ensure the tree is balanced, after a deletion operation.
349 CHILD was a grandchild of PARENT and is now its child. Between them,
350 a black node was removed. CHILD is also black, or NULL.
351 (CHILD can also be NULL. But PARENT is non-NULL.) */
352 static void
353 rebalance_after_remove (gl_list_t list, gl_list_node_t child, gl_list_node_t parent)
355 for (;;)
357 /* At this point, we reduced the black-height of the CHILD subtree by 1.
358 To make up, either look for a possibility to turn a RED to a BLACK
359 node, or try to reduce the black-height tree of CHILD's sibling
360 subtree as well. */
361 gl_list_node_t *parentp;
363 if (parent->parent == NULL)
364 parentp = &list->root;
365 else if (parent->parent->left == parent)
366 parentp = &parent->parent->left;
367 else if (parent->parent->right == parent)
368 parentp = &parent->parent->right;
369 else
370 abort ();
372 if (parent->left == child)
374 gl_list_node_t sibling = parent->right;
375 /* sibling's black-height is >= 1. In particular,
376 sibling != NULL.
378 parent
380 child sibling
381 bh bh+1
384 if (sibling->color == RED)
386 /* sibling is RED, hence parent is BLACK and sibling's children
387 are non-NULL and BLACK.
389 parent sibling
390 bh+2 bh+2
391 / \ / \
392 child sibling --> parent SR
393 bh bh+1 bh+1 bh+1
394 / \ / \
395 SL SR child SL
396 bh+1 bh+1 bh bh+1
398 *parentp = rotate_left (parent, sibling);
399 parent->color = RED;
400 sibling->color = BLACK;
402 /* Concentrate on the subtree of parent. The new sibling is
403 one of the old sibling's children, and known to be BLACK. */
404 parentp = &sibling->left;
405 sibling = parent->right;
407 /* Now we know that sibling is BLACK.
409 parent
411 child sibling
412 bh bh+1
414 if (sibling->right != NULL && sibling->right->color == RED)
417 parent sibling
418 bh+1|bh+2 bh+1|bh+2
419 / \ / \
420 child sibling --> parent SR
421 bh bh+1 bh+1 bh+1
422 / \ / \
423 SL SR child SL
424 bh bh bh bh
426 *parentp = rotate_left (parent, sibling);
427 sibling->color = parent->color;
428 parent->color = BLACK;
429 sibling->right->color = BLACK;
430 return;
432 else if (sibling->left != NULL && sibling->left->color == RED)
435 parent parent
436 bh+1|bh+2 bh+1|bh+2
437 / \ / \
438 child sibling --> child SL
439 bh bh+1 bh bh+1
440 / \ / \
441 SL SR SLL sibling
442 bh bh bh bh
443 / \ / \
444 SLL SLR SLR SR
445 bh bh bh bh
447 where SLL, SLR, SR are all black.
449 parent->right = rotate_right (sibling->left, sibling);
450 /* Change sibling from BLACK to RED and SL from RED to BLACK. */
451 sibling->color = RED;
452 sibling = parent->right;
453 sibling->color = BLACK;
455 /* Now do as in the previous case. */
456 *parentp = rotate_left (parent, sibling);
457 sibling->color = parent->color;
458 parent->color = BLACK;
459 sibling->right->color = BLACK;
460 return;
462 else
464 if (parent->color == BLACK)
466 /* Change sibling from BLACK to RED. Then the entire
467 subtree at parent has decreased its black-height.
468 parent parent
469 bh+2 bh+1
470 / \ / \
471 child sibling --> child sibling
472 bh bh+1 bh bh
474 sibling->color = RED;
476 child = parent;
478 else
480 /* Change parent from RED to BLACK, but compensate by
481 changing sibling from BLACK to RED.
482 parent parent
483 bh+1 bh+1
484 / \ / \
485 child sibling --> child sibling
486 bh bh+1 bh bh
488 parent->color = BLACK;
489 sibling->color = RED;
490 return;
494 else if (parent->right == child)
496 gl_list_node_t sibling = parent->left;
497 /* sibling's black-height is >= 1. In particular,
498 sibling != NULL.
500 parent
502 sibling child
503 bh+1 bh
506 if (sibling->color == RED)
508 /* sibling is RED, hence parent is BLACK and sibling's children
509 are non-NULL and BLACK.
511 parent sibling
512 bh+2 bh+2
513 / \ / \
514 sibling child --> SR parent
515 bh+1 ch bh+1 bh+1
516 / \ / \
517 SL SR SL child
518 bh+1 bh+1 bh+1 bh
520 *parentp = rotate_right (sibling, parent);
521 parent->color = RED;
522 sibling->color = BLACK;
524 /* Concentrate on the subtree of parent. The new sibling is
525 one of the old sibling's children, and known to be BLACK. */
526 parentp = &sibling->right;
527 sibling = parent->left;
529 /* Now we know that sibling is BLACK.
531 parent
533 sibling child
534 bh+1 bh
536 if (sibling->left != NULL && sibling->left->color == RED)
539 parent sibling
540 bh+1|bh+2 bh+1|bh+2
541 / \ / \
542 sibling child --> SL parent
543 bh+1 bh bh+1 bh+1
544 / \ / \
545 SL SR SR child
546 bh bh bh bh
548 *parentp = rotate_right (sibling, parent);
549 sibling->color = parent->color;
550 parent->color = BLACK;
551 sibling->left->color = BLACK;
552 return;
554 else if (sibling->right != NULL && sibling->right->color == RED)
557 parent parent
558 bh+1|bh+2 bh+1|bh+2
559 / \ / \
560 sibling child --> SR child
561 bh+1 bh bh+1 bh
562 / \ / \
563 SL SR sibling SRR
564 bh bh bh bh
565 / \ / \
566 SRL SRR SL SRL
567 bh bh bh bh
569 where SL, SRL, SRR are all black.
571 parent->left = rotate_left (sibling, sibling->right);
572 /* Change sibling from BLACK to RED and SL from RED to BLACK. */
573 sibling->color = RED;
574 sibling = parent->left;
575 sibling->color = BLACK;
577 /* Now do as in the previous case. */
578 *parentp = rotate_right (sibling, parent);
579 sibling->color = parent->color;
580 parent->color = BLACK;
581 sibling->left->color = BLACK;
582 return;
584 else
586 if (parent->color == BLACK)
588 /* Change sibling from BLACK to RED. Then the entire
589 subtree at parent has decreased its black-height.
590 parent parent
591 bh+2 bh+1
592 / \ / \
593 sibling child --> sibling child
594 bh+1 bh bh bh
596 sibling->color = RED;
598 child = parent;
600 else
602 /* Change parent from RED to BLACK, but compensate by
603 changing sibling from BLACK to RED.
604 parent parent
605 bh+1 bh+1
606 / \ / \
607 sibling child --> sibling child
608 bh+1 bh bh bh
610 parent->color = BLACK;
611 sibling->color = RED;
612 return;
616 else
617 abort ();
619 /* Start again with a new (child, parent) pair. */
620 parent = child->parent;
622 #if 0 /* Already handled. */
623 if (child != NULL && child->color == RED)
625 child->color = BLACK;
626 return;
628 #endif
630 if (parent == NULL)
631 return;
635 static void
636 gl_tree_remove_node_from_tree (gl_list_t list, gl_list_node_t node)
638 gl_list_node_t parent = node->parent;
640 if (node->left == NULL)
642 /* Replace node with node->right. */
643 gl_list_node_t child = node->right;
645 if (child != NULL)
647 child->parent = parent;
648 /* Since node->left == NULL, child must be RED and of height 1,
649 hence node must have been BLACK. Recolor the child. */
650 child->color = BLACK;
652 if (parent == NULL)
653 list->root = child;
654 else
656 if (parent->left == node)
657 parent->left = child;
658 else /* parent->right == node */
659 parent->right = child;
661 /* Update branch_size fields of the parent nodes. */
663 gl_list_node_t p;
665 for (p = parent; p != NULL; p = p->parent)
666 p->branch_size--;
669 if (child == NULL && node->color == BLACK)
670 rebalance_after_remove (list, child, parent);
673 else if (node->right == NULL)
675 /* It is not absolutely necessary to treat this case. But the more
676 general case below is more complicated, hence slower. */
677 /* Replace node with node->left. */
678 gl_list_node_t child = node->left;
680 child->parent = parent;
681 /* Since node->right == NULL, child must be RED and of height 1,
682 hence node must have been BLACK. Recolor the child. */
683 child->color = BLACK;
684 if (parent == NULL)
685 list->root = child;
686 else
688 if (parent->left == node)
689 parent->left = child;
690 else /* parent->right == node */
691 parent->right = child;
693 /* Update branch_size fields of the parent nodes. */
695 gl_list_node_t p;
697 for (p = parent; p != NULL; p = p->parent)
698 p->branch_size--;
702 else
704 /* Replace node with the rightmost element of the node->left subtree. */
705 gl_list_node_t subst;
706 gl_list_node_t subst_parent;
707 gl_list_node_t child;
708 color_t removed_color;
710 for (subst = node->left; subst->right != NULL; )
711 subst = subst->right;
713 subst_parent = subst->parent;
715 child = subst->left;
717 removed_color = subst->color;
719 /* The case subst_parent == node is special: If we do nothing special,
720 we get confusion about node->left, subst->left and child->parent.
721 subst_parent == node
722 <==> The 'for' loop above terminated immediately.
723 <==> subst == subst_parent->left
724 [otherwise subst == subst_parent->right]
725 In this case, we would need to first set
726 child->parent = node; node->left = child;
727 and later - when we copy subst into node's position - again
728 child->parent = subst; subst->left = child;
729 Altogether a no-op. */
730 if (subst_parent != node)
732 if (child != NULL)
733 child->parent = subst_parent;
734 subst_parent->right = child;
737 /* Update branch_size fields of the parent nodes. */
739 gl_list_node_t p;
741 for (p = subst_parent; p != NULL; p = p->parent)
742 p->branch_size--;
745 /* Copy subst into node's position.
746 (This is safer than to copy subst's value into node, keep node in
747 place, and free subst.) */
748 if (subst_parent != node)
750 subst->left = node->left;
751 subst->left->parent = subst;
753 subst->right = node->right;
754 subst->right->parent = subst;
755 subst->color = node->color;
756 subst->branch_size = node->branch_size;
757 subst->parent = parent;
758 if (parent == NULL)
759 list->root = subst;
760 else if (parent->left == node)
761 parent->left = subst;
762 else /* parent->right == node */
763 parent->right = subst;
765 if (removed_color == BLACK)
767 if (child != NULL && child->color == RED)
768 /* Recolor the child. */
769 child->color = BLACK;
770 else
771 /* Rebalancing starts at child's parent, that is subst_parent -
772 except when subst_parent == node. In this case, we need to use
773 its replacement, subst. */
774 rebalance_after_remove (list, child,
775 subst_parent != node ? subst_parent : subst);
780 static gl_list_node_t
781 gl_tree_nx_add_first (gl_list_t list, const void *elt)
783 /* Create new node. */
784 gl_list_node_t new_node =
785 (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl));
787 if (new_node == NULL)
788 return NULL;
790 new_node->left = NULL;
791 new_node->right = NULL;
792 new_node->branch_size = 1;
793 new_node->value = elt;
794 #if WITH_HASHTABLE
795 new_node->h.hashcode =
796 (list->base.hashcode_fn != NULL
797 ? list->base.hashcode_fn (new_node->value)
798 : (size_t)(uintptr_t) new_node->value);
799 #endif
801 /* Add it to the tree. */
802 if (list->root == NULL)
804 new_node->color = BLACK;
805 list->root = new_node;
806 new_node->parent = NULL;
808 else
810 gl_list_node_t node;
812 for (node = list->root; node->left != NULL; )
813 node = node->left;
815 node->left = new_node;
816 new_node->parent = node;
818 /* Update branch_size fields of the parent nodes. */
820 gl_list_node_t p;
822 for (p = node; p != NULL; p = p->parent)
823 p->branch_size++;
826 /* Color and rebalance. */
827 rebalance_after_add (list, new_node, node);
830 #if WITH_HASHTABLE
831 /* Add node to the hash table.
832 Note that this is only possible _after_ the node has been added to the
833 tree structure, because add_to_bucket() uses node_position(). */
834 if (add_to_bucket (list, new_node) < 0)
836 gl_tree_remove_node_from_tree (list, new_node);
837 free (new_node);
838 return NULL;
840 hash_resize_after_add (list);
841 #endif
843 return new_node;
846 static gl_list_node_t
847 gl_tree_nx_add_last (gl_list_t list, const void *elt)
849 /* Create new node. */
850 gl_list_node_t new_node =
851 (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl));
853 if (new_node == NULL)
854 return NULL;
856 new_node->left = NULL;
857 new_node->right = NULL;
858 new_node->branch_size = 1;
859 new_node->value = elt;
860 #if WITH_HASHTABLE
861 new_node->h.hashcode =
862 (list->base.hashcode_fn != NULL
863 ? list->base.hashcode_fn (new_node->value)
864 : (size_t)(uintptr_t) new_node->value);
865 #endif
867 /* Add it to the tree. */
868 if (list->root == NULL)
870 new_node->color = BLACK;
871 list->root = new_node;
872 new_node->parent = NULL;
874 else
876 gl_list_node_t node;
878 for (node = list->root; node->right != NULL; )
879 node = node->right;
881 node->right = new_node;
882 new_node->parent = node;
884 /* Update branch_size fields of the parent nodes. */
886 gl_list_node_t p;
888 for (p = node; p != NULL; p = p->parent)
889 p->branch_size++;
892 /* Color and rebalance. */
893 rebalance_after_add (list, new_node, node);
896 #if WITH_HASHTABLE
897 /* Add node to the hash table.
898 Note that this is only possible _after_ the node has been added to the
899 tree structure, because add_to_bucket() uses node_position(). */
900 if (add_to_bucket (list, new_node) < 0)
902 gl_tree_remove_node_from_tree (list, new_node);
903 free (new_node);
904 return NULL;
906 hash_resize_after_add (list);
907 #endif
909 return new_node;
912 static gl_list_node_t
913 gl_tree_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
915 /* Create new node. */
916 gl_list_node_t new_node =
917 (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl));
919 if (new_node == NULL)
920 return NULL;
922 new_node->left = NULL;
923 new_node->right = NULL;
924 new_node->branch_size = 1;
925 new_node->value = elt;
926 #if WITH_HASHTABLE
927 new_node->h.hashcode =
928 (list->base.hashcode_fn != NULL
929 ? list->base.hashcode_fn (new_node->value)
930 : (size_t)(uintptr_t) new_node->value);
931 #endif
933 /* Add it to the tree. */
934 if (node->left == NULL)
935 node->left = new_node;
936 else
938 for (node = node->left; node->right != NULL; )
939 node = node->right;
940 node->right = new_node;
942 new_node->parent = node;
944 /* Update branch_size fields of the parent nodes. */
946 gl_list_node_t p;
948 for (p = node; p != NULL; p = p->parent)
949 p->branch_size++;
952 /* Color and rebalance. */
953 rebalance_after_add (list, new_node, node);
955 #if WITH_HASHTABLE
956 /* Add node to the hash table.
957 Note that this is only possible _after_ the node has been added to the
958 tree structure, because add_to_bucket() uses node_position(). */
959 if (add_to_bucket (list, new_node) < 0)
961 gl_tree_remove_node_from_tree (list, new_node);
962 free (new_node);
963 return NULL;
965 hash_resize_after_add (list);
966 #endif
968 return new_node;
971 static gl_list_node_t
972 gl_tree_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
974 /* Create new node. */
975 gl_list_node_t new_node =
976 (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl));
978 if (new_node == NULL)
979 return NULL;
981 new_node->left = NULL;
982 new_node->right = NULL;
983 new_node->branch_size = 1;
984 new_node->value = elt;
985 #if WITH_HASHTABLE
986 new_node->h.hashcode =
987 (list->base.hashcode_fn != NULL
988 ? list->base.hashcode_fn (new_node->value)
989 : (size_t)(uintptr_t) new_node->value);
990 #endif
992 /* Add it to the tree. */
993 if (node->right == NULL)
994 node->right = new_node;
995 else
997 for (node = node->right; node->left != NULL; )
998 node = node->left;
999 node->left = new_node;
1001 new_node->parent = node;
1003 /* Update branch_size fields of the parent nodes. */
1005 gl_list_node_t p;
1007 for (p = node; p != NULL; p = p->parent)
1008 p->branch_size++;
1011 /* Color and rebalance. */
1012 rebalance_after_add (list, new_node, node);
1014 #if WITH_HASHTABLE
1015 /* Add node to the hash table.
1016 Note that this is only possible _after_ the node has been added to the
1017 tree structure, because add_to_bucket() uses node_position(). */
1018 if (add_to_bucket (list, new_node) < 0)
1020 gl_tree_remove_node_from_tree (list, new_node);
1021 free (new_node);
1022 return NULL;
1024 hash_resize_after_add (list);
1025 #endif
1027 return new_node;