Mercurial > gnulib
view lib/gl_anytree_list2.h @ 7352:3d5bd6899004
* gl_anylinked_list2.h [lint] (gl_linked_iterator)
(gl_linked_iterator_from_to): Initialize struct completely.
* gl_anytree_list2.h [lint] (gl_tree_iterator): Likewise.
(gl_tree_iterator_from_to): Likewise
* gl_anytree_oset.h [lint] (gl_tree_iterator): Likewise.
* gl_array_list.c [lint] (gl_array_iterator)
(gl_array_iterator_from_to): Likewise.
* gl_array_oset.c [lint] (gl_array_iterator): Likewise.
* gl_carray_list.c [lint] (gl_carray_iterator)
(gl_carray_iterator_from_to): Likewise.
author | Ralf Wildenhues <Ralf.Wildenhues@gmx.de> |
---|---|
date | Fri, 22 Sep 2006 17:15:05 +0000 |
parents | de9a21fc207a |
children | 0de49c40e105 |
line wrap: on
line source
/* Sequential list data type implemented by a binary tree. Copyright (C) 2006 Free Software Foundation, Inc. Written by Bruno Haible <bruno@clisp.org>, 2006. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Common code of gl_avltree_list.c, gl_rbtree_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c. */ static gl_list_t gl_tree_create_empty (gl_list_implementation_t implementation, gl_listelement_equals_fn equals_fn, gl_listelement_hashcode_fn hashcode_fn, bool allow_duplicates) { struct gl_list_impl *list = (struct gl_list_impl *) xmalloc (sizeof (struct gl_list_impl)); list->base.vtable = implementation; list->base.equals_fn = equals_fn; list->base.hashcode_fn = hashcode_fn; list->base.allow_duplicates = allow_duplicates; #if WITH_HASHTABLE list->table_size = 11; list->table = (gl_hash_entry_t *) xzalloc (list->table_size * sizeof (gl_hash_entry_t)); #endif list->root = NULL; return list; } static size_t gl_tree_size (gl_list_t list) { return (list->root != NULL ? list->root->branch_size : 0); } static const void * gl_tree_node_value (gl_list_t list, gl_list_node_t node) { return node->value; } static gl_list_node_t gl_tree_next_node (gl_list_t list, gl_list_node_t node) { if (node->right != NULL) { node = node->right; while (node->left != NULL) node = node->left; } else { while (node->parent != NULL && node->parent->right == node) node = node->parent; node = node->parent; } return node; } static gl_list_node_t gl_tree_previous_node (gl_list_t list, gl_list_node_t node) { if (node->left != NULL) { node = node->left; while (node->right != NULL) node = node->right; } else { while (node->parent != NULL && node->parent->left == node) node = node->parent; node = node->parent; } return node; } /* Return the node at the given position < gl_tree_size (list). */ static inline gl_list_node_t node_at (gl_list_node_t root, size_t position) { /* Here we know that root != NULL. */ gl_list_node_t node = root; for (;;) { if (node->left != NULL) { if (position < node->left->branch_size) { node = node->left; continue; } position -= node->left->branch_size; } if (position == 0) break; position--; node = node->right; } return node; } static const void * gl_tree_get_at (gl_list_t list, size_t position) { gl_list_node_t node = list->root; if (!(node != NULL && position < node->branch_size)) /* Invalid argument. */ abort (); node = node_at (node, position); return node->value; } static gl_list_node_t gl_tree_set_at (gl_list_t list, size_t position, const void *elt) { gl_list_node_t node = list->root; if (!(node != NULL && position < node->branch_size)) /* Invalid argument. */ abort (); node = node_at (node, position); #if WITH_HASHTABLE if (elt != node->value) { size_t new_hashcode = (list->base.hashcode_fn != NULL ? list->base.hashcode_fn (elt) : (size_t)(uintptr_t) elt); if (new_hashcode != node->h.hashcode) { remove_from_bucket (list, node); node->value = elt; node->h.hashcode = new_hashcode; add_to_bucket (list, node); } else node->value = elt; } #else node->value = elt; #endif return node; } #if !WITH_HASHTABLE static gl_list_node_t gl_tree_search (gl_list_t list, const void *elt) { gl_listelement_equals_fn equals = list->base.equals_fn; /* Iterate across all elements. */ gl_list_node_t node = list->root; iterstack_t stack; iterstack_item_t *stack_ptr = &stack[0]; for (;;) { /* Descend on left branch. */ for (;;) { if (node == NULL) break; stack_ptr->node = node; stack_ptr->rightp = false; node = node->left; stack_ptr++; } /* Climb up again. */ for (;;) { if (stack_ptr == &stack[0]) return NULL; stack_ptr--; if (!stack_ptr->rightp) break; } node = stack_ptr->node; /* Test against current element. */ if (equals != NULL ? equals (elt, node->value) : elt == node->value) return node; /* Descend on right branch. */ stack_ptr->rightp = true; node = node->right; stack_ptr++; } } static size_t gl_tree_indexof (gl_list_t list, const void *elt) { gl_listelement_equals_fn equals = list->base.equals_fn; /* Iterate across all elements. */ gl_list_node_t node = list->root; iterstack_t stack; iterstack_item_t *stack_ptr = &stack[0]; size_t index = 0; for (;;) { /* Descend on left branch. */ for (;;) { if (node == NULL) break; stack_ptr->node = node; stack_ptr->rightp = false; node = node->left; stack_ptr++; } /* Climb up again. */ for (;;) { if (stack_ptr == &stack[0]) return (size_t)(-1); stack_ptr--; if (!stack_ptr->rightp) break; } node = stack_ptr->node; /* Test against current element. */ if (equals != NULL ? equals (elt, node->value) : elt == node->value) return index; index++; /* Descend on right branch. */ stack_ptr->rightp = true; node = node->right; stack_ptr++; } } #endif static gl_list_node_t gl_tree_add_at (gl_list_t list, size_t position, const void *elt) { size_t count = (list->root != NULL ? list->root->branch_size : 0); if (!(position <= count)) /* Invalid argument. */ abort (); if (position == count) return gl_tree_add_last (list, elt); else return gl_tree_add_before (list, node_at (list->root, position), elt); } static bool gl_tree_remove_at (gl_list_t list, size_t position) { gl_list_node_t node = list->root; if (!(node != NULL && position < node->branch_size)) /* Invalid argument. */ abort (); node = node_at (node, position); return gl_tree_remove_node (list, node); } static bool gl_tree_remove (gl_list_t list, const void *elt) { gl_list_node_t node = gl_tree_search (list, elt); if (node != NULL) return gl_tree_remove_node (list, node); else return false; } #if !WITH_HASHTABLE static void gl_tree_list_free (gl_list_t list) { /* Iterate across all elements in post-order. */ gl_list_node_t node = list->root; iterstack_t stack; iterstack_item_t *stack_ptr = &stack[0]; for (;;) { /* Descend on left branch. */ for (;;) { if (node == NULL) break; stack_ptr->node = node; stack_ptr->rightp = false; node = node->left; stack_ptr++; } /* Climb up again. */ for (;;) { if (stack_ptr == &stack[0]) goto done_iterate; stack_ptr--; node = stack_ptr->node; if (!stack_ptr->rightp) break; /* Free the current node. */ free (node); } /* Descend on right branch. */ stack_ptr->rightp = true; node = node->right; stack_ptr++; } done_iterate: free (list); } #endif /* --------------------- gl_list_iterator_t Data Type --------------------- */ static gl_list_iterator_t gl_tree_iterator (gl_list_t list) { gl_list_iterator_t result; gl_list_node_t node; result.vtable = list->base.vtable; result.list = list; /* Start node is the leftmost node. */ node = list->root; if (node != NULL) while (node->left != NULL) node = node->left; result.p = node; /* End point is past the rightmost node. */ result.q = NULL; #ifdef lint result.i = 0; result.j = 0; result.count = 0; #endif return result; } static gl_list_iterator_t gl_tree_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index) { size_t count = (list->root != NULL ? list->root->branch_size : 0); gl_list_iterator_t result; if (!(start_index <= end_index && end_index <= count)) /* Invalid arguments. */ abort (); result.vtable = list->base.vtable; result.list = list; /* Start node is the node at position start_index. */ result.p = (start_index < count ? node_at (list->root, start_index) : NULL); /* End point is the node at position end_index. */ result.q = (end_index < count ? node_at (list->root, end_index) : NULL); #ifdef lint result.i = 0; result.j = 0; result.count = 0; #endif return result; } static bool gl_tree_iterator_next (gl_list_iterator_t *iterator, const void **eltp, gl_list_node_t *nodep) { if (iterator->p != iterator->q) { gl_list_node_t node = (gl_list_node_t) iterator->p; *eltp = node->value; if (nodep != NULL) *nodep = node; /* Advance to the next node. */ if (node->right != NULL) { node = node->right; while (node->left != NULL) node = node->left; } else { while (node->parent != NULL && node->parent->right == node) node = node->parent; node = node->parent; } iterator->p = node; return true; } else return false; } static void gl_tree_iterator_free (gl_list_iterator_t *iterator) { } /* ---------------------- Sorted gl_list_t Data Type ---------------------- */ static gl_list_node_t gl_tree_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) { gl_list_node_t node; for (node = list->root; node != NULL; ) { int cmp = compar (node->value, elt); if (cmp < 0) node = node->right; else if (cmp > 0) node = node->left; else /* cmp == 0 */ { /* We have an element equal to ELT. But we need the leftmost such element. */ gl_list_node_t found = node; node = node->left; for (; node != NULL; ) { int cmp2 = compar (node->value, elt); if (cmp2 < 0) node = node->right; else if (cmp2 > 0) /* The list was not sorted. */ abort (); else /* cmp2 == 0 */ { found = node; node = node->left; } } return found; } } return NULL; } static size_t gl_tree_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) { gl_list_node_t node; size_t position; for (node = list->root, position = 0; node != NULL; ) { int cmp = compar (node->value, elt); if (cmp < 0) { if (node->left != NULL) position += node->left->branch_size; position++; node = node->right; } else if (cmp > 0) node = node->left; else /* cmp == 0 */ { /* We have an element equal to ELT. But we need the leftmost such element. */ size_t found_position = position + (node->left != NULL ? node->left->branch_size : 0); node = node->left; for (; node != NULL; ) { int cmp2 = compar (node->value, elt); if (cmp2 < 0) { if (node->left != NULL) position += node->left->branch_size; position++; node = node->right; } else if (cmp2 > 0) /* The list was not sorted. */ abort (); else /* cmp2 == 0 */ { found_position = position + (node->left != NULL ? node->left->branch_size : 0); node = node->left; } } return found_position; } } return (size_t)(-1); } static gl_list_node_t gl_tree_sortedlist_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) { gl_list_node_t node = list->root; if (node == NULL) return gl_tree_add_first (list, elt); for (;;) { int cmp = compar (node->value, elt); if (cmp < 0) { if (node->right == NULL) return gl_tree_add_after (list, node, elt); node = node->right; } else if (cmp > 0) { if (node->left == NULL) return gl_tree_add_before (list, node, elt); node = node->left; } else /* cmp == 0 */ return gl_tree_add_before (list, node, elt); } } static bool gl_tree_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) { gl_list_node_t node = gl_tree_sortedlist_search (list, compar, elt); if (node != NULL) return gl_tree_remove_node (list, node); else return false; }