glob: fix heap buffer overflow
[gnulib.git] / lib / gl_anytree_list2.h
blob19f82b050bba1ce48d15f4e5256b7ef977d4c4ff
1 /* Sequential list data type implemented by a binary tree.
2 Copyright (C) 2006-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 <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. */
21 static gl_list_t
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));
30 if (list == NULL)
31 return NULL;
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;
38 #if WITH_HASHTABLE
39 list->table_size = 11;
40 list->table =
41 (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t));
42 if (list->table == NULL)
43 goto fail;
44 #endif
45 list->root = NULL;
47 return list;
49 #if WITH_HASHTABLE
50 fail:
51 free (list);
52 return NULL;
53 #endif
56 static size_t
57 gl_tree_size (gl_list_t list)
59 return (list->root != NULL ? list->root->branch_size : 0);
62 static const void *
63 gl_tree_node_value (gl_list_t list, gl_list_node_t node)
65 return node->value;
68 static int
69 gl_tree_node_nx_set_value (gl_list_t list, gl_list_node_t node, const void *elt)
71 #if WITH_HASHTABLE
72 if (elt != node->value)
74 size_t new_hashcode =
75 (list->base.hashcode_fn != NULL
76 ? list->base.hashcode_fn (elt)
77 : (size_t)(uintptr_t) elt);
79 if (new_hashcode != node->h.hashcode)
81 remove_from_bucket (list, node);
82 node->value = elt;
83 node->h.hashcode = new_hashcode;
84 if (add_to_bucket (list, node) < 0)
86 /* Out of memory. We removed node from a bucket but cannot add
87 it to another bucket. In order to avoid inconsistencies, we
88 must remove node entirely from the list. */
89 gl_tree_remove_node_from_tree (list, node);
90 free (node);
91 return -1;
94 else
95 node->value = elt;
97 #else
98 node->value = elt;
99 #endif
100 return 0;
103 static gl_list_node_t _GL_ATTRIBUTE_PURE
104 gl_tree_next_node (gl_list_t list, gl_list_node_t node)
106 if (node->right != NULL)
108 node = node->right;
109 while (node->left != NULL)
110 node = node->left;
112 else
114 while (node->parent != NULL && node->parent->right == node)
115 node = node->parent;
116 node = node->parent;
118 return node;
121 static gl_list_node_t _GL_ATTRIBUTE_PURE
122 gl_tree_previous_node (gl_list_t list, gl_list_node_t node)
124 if (node->left != NULL)
126 node = node->left;
127 while (node->right != NULL)
128 node = node->right;
130 else
132 while (node->parent != NULL && node->parent->left == node)
133 node = node->parent;
134 node = node->parent;
136 return node;
139 /* Return the node at the given position < gl_tree_size (list). */
140 static gl_list_node_t _GL_ATTRIBUTE_PURE
141 node_at (gl_list_node_t root, size_t position)
143 /* Here we know that root != NULL. */
144 gl_list_node_t node = root;
146 for (;;)
148 if (node->left != NULL)
150 if (position < node->left->branch_size)
152 node = node->left;
153 continue;
155 position -= node->left->branch_size;
157 if (position == 0)
158 break;
159 position--;
160 node = node->right;
162 return node;
165 static const void * _GL_ATTRIBUTE_PURE
166 gl_tree_get_at (gl_list_t list, size_t position)
168 gl_list_node_t node = list->root;
170 if (!(node != NULL && position < node->branch_size))
171 /* Invalid argument. */
172 abort ();
173 node = node_at (node, position);
174 return node->value;
177 static gl_list_node_t
178 gl_tree_nx_set_at (gl_list_t list, size_t position, const void *elt)
180 gl_list_node_t node = list->root;
182 if (!(node != NULL && position < node->branch_size))
183 /* Invalid argument. */
184 abort ();
185 node = node_at (node, position);
186 #if WITH_HASHTABLE
187 if (elt != node->value)
189 size_t new_hashcode =
190 (list->base.hashcode_fn != NULL
191 ? list->base.hashcode_fn (elt)
192 : (size_t)(uintptr_t) elt);
194 if (new_hashcode != node->h.hashcode)
196 remove_from_bucket (list, node);
197 node->value = elt;
198 node->h.hashcode = new_hashcode;
199 if (add_to_bucket (list, node) < 0)
201 /* Out of memory. We removed node from a bucket but cannot add
202 it to another bucket. In order to avoid inconsistencies, we
203 must remove node entirely from the list. */
204 gl_tree_remove_node_from_tree (list, node);
205 free (node);
206 return NULL;
209 else
210 node->value = elt;
212 #else
213 node->value = elt;
214 #endif
215 return node;
218 #if !WITH_HASHTABLE
220 static gl_list_node_t
221 gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
222 const void *elt)
224 if (!(start_index <= end_index
225 && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
226 /* Invalid arguments. */
227 abort ();
229 gl_listelement_equals_fn equals = list->base.equals_fn;
230 /* Iterate across all elements. */
231 gl_list_node_t node = list->root;
232 iterstack_t stack;
233 iterstack_item_t *stack_ptr = &stack[0];
234 size_t index = 0;
236 if (start_index == 0)
238 /* Consider all elements. */
239 for (;;)
241 /* Descend on left branch. */
242 for (;;)
244 if (node == NULL)
245 break;
246 stack_ptr->node = node;
247 stack_ptr->rightp = 0;
248 node = node->left;
249 stack_ptr++;
251 /* Climb up again. */
252 for (;;)
254 if (stack_ptr == &stack[0])
255 return NULL;
256 stack_ptr--;
257 if (!stack_ptr->rightp)
258 break;
260 node = stack_ptr->node;
261 /* Test against current element. */
262 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
263 return node;
264 index++;
265 if (index >= end_index)
266 return NULL;
267 /* Descend on right branch. */
268 stack_ptr->rightp = 1;
269 node = node->right;
270 stack_ptr++;
273 else
275 /* Consider only elements at indices >= start_index.
276 In this case, rightp contains the difference between the start_index
277 for the parent node and the one for the child node (0 when the child
278 node is the parent's left child, > 0 when the child is the parent's
279 right child). */
280 for (;;)
282 /* Descend on left branch. */
283 for (;;)
285 if (node == NULL)
286 break;
287 if (node->branch_size <= start_index)
288 break;
289 stack_ptr->node = node;
290 stack_ptr->rightp = 0;
291 node = node->left;
292 stack_ptr++;
294 /* Climb up again. */
295 for (;;)
297 if (stack_ptr == &stack[0])
298 return NULL;
299 stack_ptr--;
300 if (!stack_ptr->rightp)
301 break;
302 start_index += stack_ptr->rightp;
304 node = stack_ptr->node;
306 size_t left_branch_size1 =
307 (node->left != NULL ? node->left->branch_size : 0) + 1;
308 if (start_index < left_branch_size1)
310 /* Test against current element. */
311 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
312 return node;
313 /* Now that we have considered all indices < left_branch_size1,
314 we can increment start_index. */
315 start_index = left_branch_size1;
317 index++;
318 if (index >= end_index)
319 return NULL;
320 /* Descend on right branch. */
321 start_index -= left_branch_size1;
322 stack_ptr->rightp = left_branch_size1;
324 node = node->right;
325 stack_ptr++;
331 static size_t
332 gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
333 const void *elt)
335 if (!(start_index <= end_index
336 && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
337 /* Invalid arguments. */
338 abort ();
340 gl_listelement_equals_fn equals = list->base.equals_fn;
341 /* Iterate across all elements. */
342 gl_list_node_t node = list->root;
343 iterstack_t stack;
344 iterstack_item_t *stack_ptr = &stack[0];
345 size_t index = 0;
347 if (start_index == 0)
349 /* Consider all elements. */
350 for (;;)
352 /* Descend on left branch. */
353 for (;;)
355 if (node == NULL)
356 break;
357 stack_ptr->node = node;
358 stack_ptr->rightp = 0;
359 node = node->left;
360 stack_ptr++;
362 /* Climb up again. */
363 for (;;)
365 if (stack_ptr == &stack[0])
366 return (size_t)(-1);
367 stack_ptr--;
368 if (!stack_ptr->rightp)
369 break;
371 node = stack_ptr->node;
372 /* Test against current element. */
373 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
374 return index;
375 index++;
376 if (index >= end_index)
377 return (size_t)(-1);
378 /* Descend on right branch. */
379 stack_ptr->rightp = 1;
380 node = node->right;
381 stack_ptr++;
384 else
386 /* Consider only elements at indices >= start_index.
387 In this case, rightp contains the difference between the start_index
388 for the parent node and the one for the child node (0 when the child
389 node is the parent's left child, > 0 when the child is the parent's
390 right child). */
391 for (;;)
393 /* Descend on left branch. */
394 for (;;)
396 if (node == NULL)
397 break;
398 if (node->branch_size <= start_index)
399 break;
400 stack_ptr->node = node;
401 stack_ptr->rightp = 0;
402 node = node->left;
403 stack_ptr++;
405 /* Climb up again. */
406 for (;;)
408 if (stack_ptr == &stack[0])
409 return (size_t)(-1);
410 stack_ptr--;
411 if (!stack_ptr->rightp)
412 break;
413 start_index += stack_ptr->rightp;
415 node = stack_ptr->node;
417 size_t left_branch_size1 =
418 (node->left != NULL ? node->left->branch_size : 0) + 1;
419 if (start_index < left_branch_size1)
421 /* Test against current element. */
422 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
423 return index;
424 /* Now that we have considered all indices < left_branch_size1,
425 we can increment start_index. */
426 start_index = left_branch_size1;
428 index++;
429 if (index >= end_index)
430 return (size_t)(-1);
431 /* Descend on right branch. */
432 start_index -= left_branch_size1;
433 stack_ptr->rightp = left_branch_size1;
435 node = node->right;
436 stack_ptr++;
442 #endif
444 static gl_list_node_t
445 gl_tree_nx_add_at (gl_list_t list, size_t position, const void *elt)
447 size_t count = (list->root != NULL ? list->root->branch_size : 0);
449 if (!(position <= count))
450 /* Invalid argument. */
451 abort ();
452 if (position == count)
453 return gl_tree_nx_add_last (list, elt);
454 else
455 return gl_tree_nx_add_before (list, node_at (list->root, position), elt);
458 static bool
459 gl_tree_remove_node (gl_list_t list, gl_list_node_t node)
461 #if WITH_HASHTABLE
462 /* Remove node from the hash table.
463 Note that this is only possible _before_ the node is removed from the
464 tree structure, because remove_from_bucket() uses node_position(). */
465 remove_from_bucket (list, node);
466 #endif
468 gl_tree_remove_node_from_tree (list, node);
470 if (list->base.dispose_fn != NULL)
471 list->base.dispose_fn (node->value);
472 free (node);
473 return true;
476 static bool
477 gl_tree_remove_at (gl_list_t list, size_t position)
479 gl_list_node_t node = list->root;
481 if (!(node != NULL && position < node->branch_size))
482 /* Invalid argument. */
483 abort ();
484 node = node_at (node, position);
485 return gl_tree_remove_node (list, node);
488 static bool
489 gl_tree_remove (gl_list_t list, const void *elt)
491 if (list->root != NULL)
493 gl_list_node_t node =
494 gl_tree_search_from_to (list, 0, list->root->branch_size, elt);
496 if (node != NULL)
497 return gl_tree_remove_node (list, node);
499 return false;
502 #if !WITH_HASHTABLE
504 static void
505 gl_tree_list_free (gl_list_t list)
507 /* Iterate across all elements in post-order. */
508 gl_list_node_t node = list->root;
509 iterstack_t stack;
510 iterstack_item_t *stack_ptr = &stack[0];
512 for (;;)
514 /* Descend on left branch. */
515 for (;;)
517 if (node == NULL)
518 break;
519 stack_ptr->node = node;
520 stack_ptr->rightp = false;
521 node = node->left;
522 stack_ptr++;
524 /* Climb up again. */
525 for (;;)
527 if (stack_ptr == &stack[0])
528 goto done_iterate;
529 stack_ptr--;
530 node = stack_ptr->node;
531 if (!stack_ptr->rightp)
532 break;
533 /* Free the current node. */
534 if (list->base.dispose_fn != NULL)
535 list->base.dispose_fn (node->value);
536 free (node);
538 /* Descend on right branch. */
539 stack_ptr->rightp = true;
540 node = node->right;
541 stack_ptr++;
543 done_iterate:
544 free (list);
547 #endif
549 /* --------------------- gl_list_iterator_t Data Type --------------------- */
551 static gl_list_iterator_t
552 gl_tree_iterator (gl_list_t list)
554 gl_list_iterator_t result;
555 gl_list_node_t node;
557 result.vtable = list->base.vtable;
558 result.list = list;
559 /* Start node is the leftmost node. */
560 node = list->root;
561 if (node != NULL)
562 while (node->left != NULL)
563 node = node->left;
564 result.p = node;
565 /* End point is past the rightmost node. */
566 result.q = NULL;
567 #if defined GCC_LINT || defined lint
568 result.i = 0;
569 result.j = 0;
570 result.count = 0;
571 #endif
573 return result;
576 static gl_list_iterator_t
577 gl_tree_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
579 size_t count = (list->root != NULL ? list->root->branch_size : 0);
580 gl_list_iterator_t result;
582 if (!(start_index <= end_index && end_index <= count))
583 /* Invalid arguments. */
584 abort ();
585 result.vtable = list->base.vtable;
586 result.list = list;
587 /* Start node is the node at position start_index. */
588 result.p = (start_index < count ? node_at (list->root, start_index) : NULL);
589 /* End point is the node at position end_index. */
590 result.q = (end_index < count ? node_at (list->root, end_index) : NULL);
591 #if defined GCC_LINT || defined lint
592 result.i = 0;
593 result.j = 0;
594 result.count = 0;
595 #endif
597 return result;
600 static bool
601 gl_tree_iterator_next (gl_list_iterator_t *iterator,
602 const void **eltp, gl_list_node_t *nodep)
604 if (iterator->p != iterator->q)
606 gl_list_node_t node = (gl_list_node_t) iterator->p;
607 *eltp = node->value;
608 if (nodep != NULL)
609 *nodep = node;
610 /* Advance to the next node. */
611 if (node->right != NULL)
613 node = node->right;
614 while (node->left != NULL)
615 node = node->left;
617 else
619 while (node->parent != NULL && node->parent->right == node)
620 node = node->parent;
621 node = node->parent;
623 iterator->p = node;
624 return true;
626 else
627 return false;
630 static void
631 gl_tree_iterator_free (gl_list_iterator_t *iterator)
635 /* ---------------------- Sorted gl_list_t Data Type ---------------------- */
637 static gl_list_node_t
638 gl_tree_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar,
639 const void *elt)
641 gl_list_node_t node;
643 for (node = list->root; node != NULL; )
645 int cmp = compar (node->value, elt);
647 if (cmp < 0)
648 node = node->right;
649 else if (cmp > 0)
650 node = node->left;
651 else /* cmp == 0 */
653 /* We have an element equal to ELT. But we need the leftmost such
654 element. */
655 gl_list_node_t found = node;
656 node = node->left;
657 for (; node != NULL; )
659 int cmp2 = compar (node->value, elt);
661 if (cmp2 < 0)
662 node = node->right;
663 else if (cmp2 > 0)
664 /* The list was not sorted. */
665 abort ();
666 else /* cmp2 == 0 */
668 found = node;
669 node = node->left;
672 return found;
675 return NULL;
678 static gl_list_node_t
679 gl_tree_sortedlist_search_from_to (gl_list_t list,
680 gl_listelement_compar_fn compar,
681 size_t low, size_t high,
682 const void *elt)
684 gl_list_node_t node;
686 if (!(low <= high
687 && high <= (list->root != NULL ? list->root->branch_size : 0)))
688 /* Invalid arguments. */
689 abort ();
691 for (node = list->root; node != NULL; )
693 size_t left_branch_size =
694 (node->left != NULL ? node->left->branch_size : 0);
696 if (low > left_branch_size)
698 low -= left_branch_size + 1;
699 high -= left_branch_size + 1;
700 node = node->right;
702 else if (high <= left_branch_size)
703 node = node->left;
704 else
706 /* Here low <= left_branch_size < high. */
707 int cmp = compar (node->value, elt);
709 if (cmp < 0)
711 low = 0;
712 high -= left_branch_size + 1;
713 node = node->right;
715 else if (cmp > 0)
716 node = node->left;
717 else /* cmp == 0 */
719 /* We have an element equal to ELT. But we need the leftmost
720 such element. */
721 gl_list_node_t found = node;
722 node = node->left;
723 for (; node != NULL; )
725 size_t left_branch_size2 =
726 (node->left != NULL ? node->left->branch_size : 0);
728 if (low > left_branch_size2)
730 low -= left_branch_size2 + 1;
731 node = node->right;
733 else
735 /* Here low <= left_branch_size2. */
736 int cmp2 = compar (node->value, elt);
738 if (cmp2 < 0)
740 low = 0;
741 node = node->right;
743 else if (cmp2 > 0)
744 /* The list was not sorted. */
745 abort ();
746 else /* cmp2 == 0 */
748 found = node;
749 node = node->left;
753 return found;
757 return NULL;
760 static size_t
761 gl_tree_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar,
762 const void *elt)
764 gl_list_node_t node;
765 size_t position;
767 for (node = list->root, position = 0; node != NULL; )
769 int cmp = compar (node->value, elt);
771 if (cmp < 0)
773 if (node->left != NULL)
774 position += node->left->branch_size;
775 position++;
776 node = node->right;
778 else if (cmp > 0)
779 node = node->left;
780 else /* cmp == 0 */
782 /* We have an element equal to ELT. But we need the leftmost such
783 element. */
784 size_t found_position =
785 position + (node->left != NULL ? node->left->branch_size : 0);
786 node = node->left;
787 for (; node != NULL; )
789 int cmp2 = compar (node->value, elt);
791 if (cmp2 < 0)
793 if (node->left != NULL)
794 position += node->left->branch_size;
795 position++;
796 node = node->right;
798 else if (cmp2 > 0)
799 /* The list was not sorted. */
800 abort ();
801 else /* cmp2 == 0 */
803 found_position =
804 position
805 + (node->left != NULL ? node->left->branch_size : 0);
806 node = node->left;
809 return found_position;
812 return (size_t)(-1);
815 static size_t
816 gl_tree_sortedlist_indexof_from_to (gl_list_t list,
817 gl_listelement_compar_fn compar,
818 size_t low, size_t high,
819 const void *elt)
821 gl_list_node_t node;
822 size_t position;
824 if (!(low <= high
825 && high <= (list->root != NULL ? list->root->branch_size : 0)))
826 /* Invalid arguments. */
827 abort ();
829 for (node = list->root, position = 0; node != NULL; )
831 size_t left_branch_size =
832 (node->left != NULL ? node->left->branch_size : 0);
834 if (low > left_branch_size)
836 low -= left_branch_size + 1;
837 high -= left_branch_size + 1;
838 position += left_branch_size + 1;
839 node = node->right;
841 else if (high <= left_branch_size)
842 node = node->left;
843 else
845 /* Here low <= left_branch_size < high. */
846 int cmp = compar (node->value, elt);
848 if (cmp < 0)
850 low = 0;
851 high -= left_branch_size + 1;
852 position += left_branch_size + 1;
853 node = node->right;
855 else if (cmp > 0)
856 node = node->left;
857 else /* cmp == 0 */
859 /* We have an element equal to ELT. But we need the leftmost
860 such element. */
861 size_t found_position =
862 position + (node->left != NULL ? node->left->branch_size : 0);
863 node = node->left;
864 for (; node != NULL; )
866 size_t left_branch_size2 =
867 (node->left != NULL ? node->left->branch_size : 0);
869 if (low > left_branch_size2)
871 low -= left_branch_size2 + 1;
872 node = node->right;
874 else
876 /* Here low <= left_branch_size2. */
877 int cmp2 = compar (node->value, elt);
879 if (cmp2 < 0)
881 position += left_branch_size2 + 1;
882 node = node->right;
884 else if (cmp2 > 0)
885 /* The list was not sorted. */
886 abort ();
887 else /* cmp2 == 0 */
889 found_position = position + left_branch_size2;
890 node = node->left;
894 return found_position;
898 return (size_t)(-1);
901 static gl_list_node_t
902 gl_tree_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar,
903 const void *elt)
905 gl_list_node_t node = list->root;
907 if (node == NULL)
908 return gl_tree_nx_add_first (list, elt);
910 for (;;)
912 int cmp = compar (node->value, elt);
914 if (cmp < 0)
916 if (node->right == NULL)
917 return gl_tree_nx_add_after (list, node, elt);
918 node = node->right;
920 else if (cmp > 0)
922 if (node->left == NULL)
923 return gl_tree_nx_add_before (list, node, elt);
924 node = node->left;
926 else /* cmp == 0 */
927 return gl_tree_nx_add_before (list, node, elt);
931 static bool
932 gl_tree_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar,
933 const void *elt)
935 gl_list_node_t node = gl_tree_sortedlist_search (list, compar, elt);
936 if (node != NULL)
937 return gl_tree_remove_node (list, node);
938 else
939 return false;