1 /* Sequential list data type implemented by a binary tree.
2 Copyright (C) 2006-2020 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 <https://www.gnu.org/licenses/>. */
18 /* Common code of gl_avltree_list.c, gl_rbtree_list.c,
19 gl_avltreehash_list.c, gl_rbtreehash_list.c. */
22 gl_tree_nx_create_empty (gl_list_implementation_t implementation
,
23 gl_listelement_equals_fn equals_fn
,
24 gl_listelement_hashcode_fn hashcode_fn
,
25 gl_listelement_dispose_fn dispose_fn
,
26 bool allow_duplicates
)
28 struct gl_list_impl
*list
= (struct gl_list_impl
*) malloc (sizeof (struct gl_list_impl
));
33 list
->base
.vtable
= implementation
;
34 list
->base
.equals_fn
= equals_fn
;
35 list
->base
.hashcode_fn
= hashcode_fn
;
36 list
->base
.dispose_fn
= dispose_fn
;
37 list
->base
.allow_duplicates
= allow_duplicates
;
39 list
->table_size
= 11;
41 (gl_hash_entry_t
*) calloc (list
->table_size
, sizeof (gl_hash_entry_t
));
42 if (list
->table
== NULL
)
56 static size_t _GL_ATTRIBUTE_PURE
57 gl_tree_size (gl_list_t list
)
59 return (list
->root
!= NULL
? list
->root
->branch_size
: 0);
62 static const void * _GL_ATTRIBUTE_PURE
63 gl_tree_node_value (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED
,
70 gl_tree_node_nx_set_value (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED
,
71 gl_list_node_t node
, const void *elt
)
74 if (elt
!= node
->value
)
77 (list
->base
.hashcode_fn
!= NULL
78 ? list
->base
.hashcode_fn (elt
)
79 : (size_t)(uintptr_t) elt
);
81 if (new_hashcode
!= node
->h
.hashcode
)
83 remove_from_bucket (list
, node
);
85 node
->h
.hashcode
= new_hashcode
;
86 if (add_to_bucket (list
, node
) < 0)
88 /* Out of memory. We removed node from a bucket but cannot add
89 it to another bucket. In order to avoid inconsistencies, we
90 must remove node entirely from the list. */
91 gl_tree_remove_node_from_tree (list
, node
);
105 static gl_list_node_t _GL_ATTRIBUTE_PURE
106 gl_tree_next_node (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED
,
109 if (node
->right
!= NULL
)
112 while (node
->left
!= NULL
)
117 while (node
->parent
!= NULL
&& node
->parent
->right
== node
)
124 static gl_list_node_t _GL_ATTRIBUTE_PURE
125 gl_tree_previous_node (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED
,
128 if (node
->left
!= NULL
)
131 while (node
->right
!= NULL
)
136 while (node
->parent
!= NULL
&& node
->parent
->left
== node
)
143 /* Returns the node at the given position < gl_tree_size (list). */
144 static gl_list_node_t _GL_ATTRIBUTE_PURE
145 node_at (gl_list_node_t root
, size_t position
)
147 /* Here we know that root != NULL. */
148 gl_list_node_t node
= root
;
152 if (node
->left
!= NULL
)
154 if (position
< node
->left
->branch_size
)
159 position
-= node
->left
->branch_size
;
169 static const void * _GL_ATTRIBUTE_PURE
170 gl_tree_get_at (gl_list_t list
, size_t position
)
172 gl_list_node_t node
= list
->root
;
174 if (!(node
!= NULL
&& position
< node
->branch_size
))
175 /* Invalid argument. */
177 node
= node_at (node
, position
);
181 static gl_list_node_t
182 gl_tree_nx_set_at (gl_list_t list
, size_t position
, const void *elt
)
184 gl_list_node_t node
= list
->root
;
186 if (!(node
!= NULL
&& position
< node
->branch_size
))
187 /* Invalid argument. */
189 node
= node_at (node
, position
);
191 if (elt
!= node
->value
)
193 size_t new_hashcode
=
194 (list
->base
.hashcode_fn
!= NULL
195 ? list
->base
.hashcode_fn (elt
)
196 : (size_t)(uintptr_t) elt
);
198 if (new_hashcode
!= node
->h
.hashcode
)
200 remove_from_bucket (list
, node
);
202 node
->h
.hashcode
= new_hashcode
;
203 if (add_to_bucket (list
, node
) < 0)
205 /* Out of memory. We removed node from a bucket but cannot add
206 it to another bucket. In order to avoid inconsistencies, we
207 must remove node entirely from the list. */
208 gl_tree_remove_node_from_tree (list
, node
);
224 static gl_list_node_t _GL_ATTRIBUTE_PURE
225 gl_tree_search_from_to (gl_list_t list
, size_t start_index
, size_t end_index
,
228 if (!(start_index
<= end_index
229 && end_index
<= (list
->root
!= NULL
? list
->root
->branch_size
: 0)))
230 /* Invalid arguments. */
233 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
234 /* Iterate across all elements. */
235 gl_list_node_t node
= list
->root
;
237 iterstack_item_t
*stack_ptr
= &stack
[0];
240 if (start_index
== 0)
242 /* Consider all elements. */
245 /* Descend on left branch. */
250 stack_ptr
->node
= node
;
251 stack_ptr
->rightp
= 0;
255 /* Climb up again. */
258 if (stack_ptr
== &stack
[0])
261 if (!stack_ptr
->rightp
)
264 node
= stack_ptr
->node
;
265 /* Test against current element. */
266 if (equals
!= NULL
? equals (elt
, node
->value
) : elt
== node
->value
)
269 if (index
>= end_index
)
271 /* Descend on right branch. */
272 stack_ptr
->rightp
= 1;
279 /* Consider only elements at indices >= start_index.
280 In this case, rightp contains the difference between the start_index
281 for the parent node and the one for the child node (0 when the child
282 node is the parent's left child, > 0 when the child is the parent's
286 /* Descend on left branch. */
291 if (node
->branch_size
<= start_index
)
293 stack_ptr
->node
= node
;
294 stack_ptr
->rightp
= 0;
298 /* Climb up again. */
301 if (stack_ptr
== &stack
[0])
304 if (!stack_ptr
->rightp
)
306 start_index
+= stack_ptr
->rightp
;
308 node
= stack_ptr
->node
;
310 size_t left_branch_size1
=
311 (node
->left
!= NULL
? node
->left
->branch_size
: 0) + 1;
312 if (start_index
< left_branch_size1
)
314 /* Test against current element. */
315 if (equals
!= NULL
? equals (elt
, node
->value
) : elt
== node
->value
)
317 /* Now that we have considered all indices < left_branch_size1,
318 we can increment start_index. */
319 start_index
= left_branch_size1
;
322 if (index
>= end_index
)
324 /* Descend on right branch. */
325 start_index
-= left_branch_size1
;
326 stack_ptr
->rightp
= left_branch_size1
;
335 static size_t _GL_ATTRIBUTE_PURE
336 gl_tree_indexof_from_to (gl_list_t list
, size_t start_index
, size_t end_index
,
339 if (!(start_index
<= end_index
340 && end_index
<= (list
->root
!= NULL
? list
->root
->branch_size
: 0)))
341 /* Invalid arguments. */
344 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
345 /* Iterate across all elements. */
346 gl_list_node_t node
= list
->root
;
348 iterstack_item_t
*stack_ptr
= &stack
[0];
351 if (start_index
== 0)
353 /* Consider all elements. */
356 /* Descend on left branch. */
361 stack_ptr
->node
= node
;
362 stack_ptr
->rightp
= 0;
366 /* Climb up again. */
369 if (stack_ptr
== &stack
[0])
372 if (!stack_ptr
->rightp
)
375 node
= stack_ptr
->node
;
376 /* Test against current element. */
377 if (equals
!= NULL
? equals (elt
, node
->value
) : elt
== node
->value
)
380 if (index
>= end_index
)
382 /* Descend on right branch. */
383 stack_ptr
->rightp
= 1;
390 /* Consider only elements at indices >= start_index.
391 In this case, rightp contains the difference between the start_index
392 for the parent node and the one for the child node (0 when the child
393 node is the parent's left child, > 0 when the child is the parent's
397 /* Descend on left branch. */
402 if (node
->branch_size
<= start_index
)
404 stack_ptr
->node
= node
;
405 stack_ptr
->rightp
= 0;
409 /* Climb up again. */
412 if (stack_ptr
== &stack
[0])
415 if (!stack_ptr
->rightp
)
417 start_index
+= stack_ptr
->rightp
;
419 node
= stack_ptr
->node
;
421 size_t left_branch_size1
=
422 (node
->left
!= NULL
? node
->left
->branch_size
: 0) + 1;
423 if (start_index
< left_branch_size1
)
425 /* Test against current element. */
426 if (equals
!= NULL
? equals (elt
, node
->value
) : elt
== node
->value
)
428 /* Now that we have considered all indices < left_branch_size1,
429 we can increment start_index. */
430 start_index
= left_branch_size1
;
433 if (index
>= end_index
)
435 /* Descend on right branch. */
436 start_index
-= left_branch_size1
;
437 stack_ptr
->rightp
= left_branch_size1
;
448 static gl_list_node_t
449 gl_tree_nx_add_at (gl_list_t list
, size_t position
, const void *elt
)
451 size_t count
= (list
->root
!= NULL
? list
->root
->branch_size
: 0);
453 if (!(position
<= count
))
454 /* Invalid argument. */
456 if (position
== count
)
457 return gl_tree_nx_add_last (list
, elt
);
459 return gl_tree_nx_add_before (list
, node_at (list
->root
, position
), elt
);
463 gl_tree_remove_node (gl_list_t list
, gl_list_node_t node
)
466 /* Remove node from the hash table.
467 Note that this is only possible _before_ the node is removed from the
468 tree structure, because remove_from_bucket() uses node_position(). */
469 remove_from_bucket (list
, node
);
472 gl_tree_remove_node_from_tree (list
, node
);
474 if (list
->base
.dispose_fn
!= NULL
)
475 list
->base
.dispose_fn (node
->value
);
481 gl_tree_remove_at (gl_list_t list
, size_t position
)
483 gl_list_node_t node
= list
->root
;
485 if (!(node
!= NULL
&& position
< node
->branch_size
))
486 /* Invalid argument. */
488 node
= node_at (node
, position
);
489 return gl_tree_remove_node (list
, node
);
493 gl_tree_remove (gl_list_t list
, const void *elt
)
495 if (list
->root
!= NULL
)
497 gl_list_node_t node
=
498 gl_tree_search_from_to (list
, 0, list
->root
->branch_size
, elt
);
501 return gl_tree_remove_node (list
, node
);
509 gl_tree_list_free (gl_list_t list
)
511 /* Iterate across all elements in post-order. */
512 gl_list_node_t node
= list
->root
;
514 iterstack_item_t
*stack_ptr
= &stack
[0];
518 /* Descend on left branch. */
523 stack_ptr
->node
= node
;
524 stack_ptr
->rightp
= false;
528 /* Climb up again. */
531 if (stack_ptr
== &stack
[0])
534 node
= stack_ptr
->node
;
535 if (!stack_ptr
->rightp
)
537 /* Free the current node. */
538 if (list
->base
.dispose_fn
!= NULL
)
539 list
->base
.dispose_fn (node
->value
);
542 /* Descend on right branch. */
543 stack_ptr
->rightp
= true;
553 /* --------------------- gl_list_iterator_t Data Type --------------------- */
555 static gl_list_iterator_t _GL_ATTRIBUTE_PURE
556 gl_tree_iterator (gl_list_t list
)
558 gl_list_iterator_t result
;
561 result
.vtable
= list
->base
.vtable
;
563 /* Start node is the leftmost node. */
566 while (node
->left
!= NULL
)
569 /* End point is past the rightmost node. */
571 #if defined GCC_LINT || defined lint
580 static gl_list_iterator_t _GL_ATTRIBUTE_PURE
581 gl_tree_iterator_from_to (gl_list_t list
, size_t start_index
, size_t end_index
)
583 size_t count
= (list
->root
!= NULL
? list
->root
->branch_size
: 0);
584 gl_list_iterator_t result
;
586 if (!(start_index
<= end_index
&& end_index
<= count
))
587 /* Invalid arguments. */
589 result
.vtable
= list
->base
.vtable
;
591 /* Start node is the node at position start_index. */
592 result
.p
= (start_index
< count
? node_at (list
->root
, start_index
) : NULL
);
593 /* End point is the node at position end_index. */
594 result
.q
= (end_index
< count
? node_at (list
->root
, end_index
) : NULL
);
595 #if defined GCC_LINT || defined lint
605 gl_tree_iterator_next (gl_list_iterator_t
*iterator
,
606 const void **eltp
, gl_list_node_t
*nodep
)
608 if (iterator
->p
!= iterator
->q
)
610 gl_list_node_t node
= (gl_list_node_t
) iterator
->p
;
614 /* Advance to the next node. */
615 if (node
->right
!= NULL
)
618 while (node
->left
!= NULL
)
623 while (node
->parent
!= NULL
&& node
->parent
->right
== node
)
634 static void _GL_ATTRIBUTE_CONST
635 gl_tree_iterator_free (gl_list_iterator_t
*iterator _GL_ATTRIBUTE_MAYBE_UNUSED
)
639 /* ---------------------- Sorted gl_list_t Data Type ---------------------- */
641 static gl_list_node_t _GL_ATTRIBUTE_PURE
642 gl_tree_sortedlist_search (gl_list_t list
, gl_listelement_compar_fn compar
,
647 for (node
= list
->root
; node
!= NULL
; )
649 int cmp
= compar (node
->value
, elt
);
657 /* We have an element equal to ELT. But we need the leftmost such
659 gl_list_node_t found
= node
;
661 for (; node
!= NULL
; )
663 int cmp2
= compar (node
->value
, elt
);
668 /* The list was not sorted. */
682 static gl_list_node_t _GL_ATTRIBUTE_PURE
683 gl_tree_sortedlist_search_from_to (gl_list_t list
,
684 gl_listelement_compar_fn compar
,
685 size_t low
, size_t high
,
691 && high
<= (list
->root
!= NULL
? list
->root
->branch_size
: 0)))
692 /* Invalid arguments. */
695 for (node
= list
->root
; node
!= NULL
; )
697 size_t left_branch_size
=
698 (node
->left
!= NULL
? node
->left
->branch_size
: 0);
700 if (low
> left_branch_size
)
702 low
-= left_branch_size
+ 1;
703 high
-= left_branch_size
+ 1;
706 else if (high
<= left_branch_size
)
710 /* Here low <= left_branch_size < high. */
711 int cmp
= compar (node
->value
, elt
);
716 high
-= left_branch_size
+ 1;
723 /* We have an element equal to ELT. But we need the leftmost
725 gl_list_node_t found
= node
;
727 for (; node
!= NULL
; )
729 size_t left_branch_size2
=
730 (node
->left
!= NULL
? node
->left
->branch_size
: 0);
732 if (low
> left_branch_size2
)
734 low
-= left_branch_size2
+ 1;
739 /* Here low <= left_branch_size2. */
740 int cmp2
= compar (node
->value
, elt
);
748 /* The list was not sorted. */
764 static size_t _GL_ATTRIBUTE_PURE
765 gl_tree_sortedlist_indexof (gl_list_t list
, gl_listelement_compar_fn compar
,
771 for (node
= list
->root
, position
= 0; node
!= NULL
; )
773 int cmp
= compar (node
->value
, elt
);
777 if (node
->left
!= NULL
)
778 position
+= node
->left
->branch_size
;
786 /* We have an element equal to ELT. But we need the leftmost such
788 size_t found_position
=
789 position
+ (node
->left
!= NULL
? node
->left
->branch_size
: 0);
791 for (; node
!= NULL
; )
793 int cmp2
= compar (node
->value
, elt
);
797 if (node
->left
!= NULL
)
798 position
+= node
->left
->branch_size
;
803 /* The list was not sorted. */
809 + (node
->left
!= NULL
? node
->left
->branch_size
: 0);
813 return found_position
;
819 static size_t _GL_ATTRIBUTE_PURE
820 gl_tree_sortedlist_indexof_from_to (gl_list_t list
,
821 gl_listelement_compar_fn compar
,
822 size_t low
, size_t high
,
829 && high
<= (list
->root
!= NULL
? list
->root
->branch_size
: 0)))
830 /* Invalid arguments. */
833 for (node
= list
->root
, position
= 0; node
!= NULL
; )
835 size_t left_branch_size
=
836 (node
->left
!= NULL
? node
->left
->branch_size
: 0);
838 if (low
> left_branch_size
)
840 low
-= left_branch_size
+ 1;
841 high
-= left_branch_size
+ 1;
842 position
+= left_branch_size
+ 1;
845 else if (high
<= left_branch_size
)
849 /* Here low <= left_branch_size < high. */
850 int cmp
= compar (node
->value
, elt
);
855 high
-= left_branch_size
+ 1;
856 position
+= left_branch_size
+ 1;
863 /* We have an element equal to ELT. But we need the leftmost
865 size_t found_position
=
866 position
+ (node
->left
!= NULL
? node
->left
->branch_size
: 0);
868 for (; node
!= NULL
; )
870 size_t left_branch_size2
=
871 (node
->left
!= NULL
? node
->left
->branch_size
: 0);
873 if (low
> left_branch_size2
)
875 low
-= left_branch_size2
+ 1;
880 /* Here low <= left_branch_size2. */
881 int cmp2
= compar (node
->value
, elt
);
885 position
+= left_branch_size2
+ 1;
889 /* The list was not sorted. */
893 found_position
= position
+ left_branch_size2
;
898 return found_position
;
905 static gl_list_node_t
906 gl_tree_sortedlist_nx_add (gl_list_t list
, gl_listelement_compar_fn compar
,
909 gl_list_node_t node
= list
->root
;
912 return gl_tree_nx_add_first (list
, elt
);
916 int cmp
= compar (node
->value
, elt
);
920 if (node
->right
== NULL
)
921 return gl_tree_nx_add_after (list
, node
, elt
);
926 if (node
->left
== NULL
)
927 return gl_tree_nx_add_before (list
, node
, elt
);
931 return gl_tree_nx_add_before (list
, node
, elt
);
936 gl_tree_sortedlist_remove (gl_list_t list
, gl_listelement_compar_fn compar
,
939 gl_list_node_t node
= gl_tree_sortedlist_search (list
, compar
, elt
);
941 return gl_tree_remove_node (list
, node
);