I wrote: > I should better revert yesterday's patch, and instead, > in the table show the guaranteed average performance > gl_list_get_first > gl_list_get_last > gl_list_set_first > gl_list_set_last > gl_list_remove_first > gl_list_remove_last > where these 6 functions are defined globally, not separately for each > implementation.
Done through the two attached patches. 2020-05-02 Bruno Haible <br...@clisp.org> list: Add get_first, get_last, set_first, set_last operations. * lib/gl_list.h (gl_list_get_first, gl_list_get_last, gl_list_nx_set_first, gl_list_nx_set_last): New functions. * lib/gl_xlist.h (gl_list_set_first, gl_list_set_last): New functions. 2020-05-02 Bruno Haible <br...@clisp.org> list: Remove redundant code for remove_first and remove_last operations. * lib/gl_list.h (struct gl_list_implementation): Remove fields remove_first, remove_last. (gl_list_remove_first, gl_list_remove_last): Implement in a generic way. * lib/gl_array_list.c: Revert last change. * lib/gl_carray_list.c: Likewise. * lib/gl_anylinked_list2.h: Likewise. * lib/gl_linked_list.c: Likewise. * lib/gl_linkedhash_list.c: Likewise. * lib/gl_anytree_list2.h: Likewise. * lib/gl_avltree_list.c: Likewise. * lib/gl_avltreehash_list.c: Likewise. * lib/gl_rbtree_list.c: Likewise. * lib/gl_rbtreehash_list.c: Likewise. * lib/gl_sublist.c: Likewise.
>From 3abe3e9a03a481163e4141e7defd30df051b42ca Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Sat, 2 May 2020 21:14:29 +0200 Subject: [PATCH 1/2] list: Remove redundant code for remove_first and remove_last operations. * lib/gl_list.h (struct gl_list_implementation): Remove fields remove_first, remove_last. (gl_list_remove_first, gl_list_remove_last): Implement in a generic way. * lib/gl_array_list.c: Revert last change. * lib/gl_carray_list.c: Likewise. * lib/gl_anylinked_list2.h: Likewise. * lib/gl_linked_list.c: Likewise. * lib/gl_linkedhash_list.c: Likewise. * lib/gl_anytree_list2.h: Likewise. * lib/gl_avltree_list.c: Likewise. * lib/gl_avltreehash_list.c: Likewise. * lib/gl_rbtree_list.c: Likewise. * lib/gl_rbtreehash_list.c: Likewise. * lib/gl_sublist.c: Likewise. --- ChangeLog | 18 ++++++++++++++ lib/gl_anylinked_list2.h | 62 ----------------------------------------------- lib/gl_anytree_list2.h | 28 --------------------- lib/gl_array_list.c | 37 ---------------------------- lib/gl_avltree_list.c | 2 -- lib/gl_avltreehash_list.c | 2 -- lib/gl_carray_list.c | 40 ------------------------------ lib/gl_linked_list.c | 2 -- lib/gl_linkedhash_list.c | 2 -- lib/gl_list.h | 16 +++++++----- lib/gl_rbtree_list.c | 2 -- lib/gl_rbtreehash_list.c | 2 -- lib/gl_sublist.c | 18 -------------- 13 files changed, 28 insertions(+), 203 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6c0f620..ac23544 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ 2020-05-02 Bruno Haible <br...@clisp.org> + list: Remove redundant code for remove_first and remove_last operations. + * lib/gl_list.h (struct gl_list_implementation): Remove fields + remove_first, remove_last. + (gl_list_remove_first, gl_list_remove_last): Implement in a generic way. + * lib/gl_array_list.c: Revert last change. + * lib/gl_carray_list.c: Likewise. + * lib/gl_anylinked_list2.h: Likewise. + * lib/gl_linked_list.c: Likewise. + * lib/gl_linkedhash_list.c: Likewise. + * lib/gl_anytree_list2.h: Likewise. + * lib/gl_avltree_list.c: Likewise. + * lib/gl_avltreehash_list.c: Likewise. + * lib/gl_rbtree_list.c: Likewise. + * lib/gl_rbtreehash_list.c: Likewise. + * lib/gl_sublist.c: Likewise. + +2020-05-02 Bruno Haible <br...@clisp.org> + bison-i18n: Add support for cross-compilation. Reported by Hongxu Jia <hongxu....@windriver.com> in <https://lists.gnu.org/archive/html/bison-patches/2016-02/msg00000.html> diff --git a/lib/gl_anylinked_list2.h b/lib/gl_anylinked_list2.h index 0032dc8..114106c 100644 --- a/lib/gl_anylinked_list2.h +++ b/lib/gl_anylinked_list2.h @@ -882,68 +882,6 @@ gl_linked_remove_at (gl_list_t list, size_t position) } static bool -gl_linked_remove_first (gl_list_t list) -{ - size_t count = list->count; - gl_list_node_t removed_node; - - if (count == 0) - return false; - /* Here we know count > 0. */ - /* Like gl_linked_remove_at (list, 0). */ - { - gl_list_node_t node; - gl_list_node_t after_removed; - - node = &list->root; - removed_node = node->next; - after_removed = node->next->next; - ASYNCSAFE(gl_list_node_t) node->next = after_removed; - after_removed->prev = node; - } -#if WITH_HASHTABLE - remove_from_bucket (list, removed_node); -#endif - list->count--; - - if (list->base.dispose_fn != NULL) - list->base.dispose_fn (removed_node->value); - free (removed_node); - return true; -} - -static bool -gl_linked_remove_last (gl_list_t list) -{ - size_t count = list->count; - gl_list_node_t removed_node; - - if (count == 0) - return false; - /* Here we know count > 0. */ - /* Like gl_linked_remove_at (list, count - 1). */ - { - gl_list_node_t node; - gl_list_node_t before_removed; - - node = &list->root; - removed_node = node->prev; - before_removed = node->prev->prev; - node->prev = before_removed; - ASYNCSAFE(gl_list_node_t) before_removed->next = node; - } -#if WITH_HASHTABLE - remove_from_bucket (list, removed_node); -#endif - list->count--; - - if (list->base.dispose_fn != NULL) - list->base.dispose_fn (removed_node->value); - free (removed_node); - return true; -} - -static bool gl_linked_remove (gl_list_t list, const void *elt) { gl_list_node_t node = gl_linked_search_from_to (list, 0, list->count, elt); diff --git a/lib/gl_anytree_list2.h b/lib/gl_anytree_list2.h index 41e41dd..c5a67db 100644 --- a/lib/gl_anytree_list2.h +++ b/lib/gl_anytree_list2.h @@ -486,34 +486,6 @@ gl_tree_remove_at (gl_list_t list, size_t position) } static bool -gl_tree_remove_first (gl_list_t list) -{ - gl_list_node_t node = list->root; - - if (node != NULL) - { - node = node_at (node, 0); - return gl_tree_remove_node (list, node); - } - else - return false; -} - -static bool -gl_tree_remove_last (gl_list_t list) -{ - gl_list_node_t node = list->root; - - if (node != NULL) - { - node = node_at (node, node->branch_size - 1); - return gl_tree_remove_node (list, node); - } - else - return false; -} - -static bool gl_tree_remove (gl_list_t list, const void *elt) { if (list->root != NULL) diff --git a/lib/gl_array_list.c b/lib/gl_array_list.c index e00255c..4950962 100644 --- a/lib/gl_array_list.c +++ b/lib/gl_array_list.c @@ -406,41 +406,6 @@ gl_array_remove_at (gl_list_t list, size_t position) } static bool -gl_array_remove_first (gl_list_t list) -{ - size_t count = list->count; - const void **elements; - size_t i; - - if (count == 0) - return false; - /* Like gl_array_remove_at (list, 0). */ - elements = list->elements; - if (list->base.dispose_fn != NULL) - list->base.dispose_fn (elements[0]); - for (i = 1; i < count; i++) - elements[i - 1] = elements[i]; - list->count = count - 1; - return true; -} - -static bool -gl_array_remove_last (gl_list_t list) -{ - size_t count = list->count; - const void **elements; - - if (count == 0) - return false; - /* Like gl_array_remove_at (list, count - 1). */ - elements = list->elements; - if (list->base.dispose_fn != NULL) - list->base.dispose_fn (elements[count - 1]); - list->count = count - 1; - return true; -} - -static bool gl_array_remove (gl_list_t list, const void *elt) { size_t position = gl_array_indexof_from_to (list, 0, list->count, elt); @@ -697,8 +662,6 @@ const struct gl_list_implementation gl_array_list_implementation = gl_array_nx_add_at, gl_array_remove_node, gl_array_remove_at, - gl_array_remove_first, - gl_array_remove_last, gl_array_remove, gl_array_list_free, gl_array_iterator, diff --git a/lib/gl_avltree_list.c b/lib/gl_avltree_list.c index 2906f5a..35ffec6 100644 --- a/lib/gl_avltree_list.c +++ b/lib/gl_avltree_list.c @@ -89,8 +89,6 @@ const struct gl_list_implementation gl_avltree_list_implementation = gl_tree_nx_add_at, gl_tree_remove_node, gl_tree_remove_at, - gl_tree_remove_first, - gl_tree_remove_last, gl_tree_remove, gl_tree_list_free, gl_tree_iterator, diff --git a/lib/gl_avltreehash_list.c b/lib/gl_avltreehash_list.c index 576f533..9f795ff 100644 --- a/lib/gl_avltreehash_list.c +++ b/lib/gl_avltreehash_list.c @@ -111,8 +111,6 @@ const struct gl_list_implementation gl_avltreehash_list_implementation = gl_tree_nx_add_at, gl_tree_remove_node, gl_tree_remove_at, - gl_tree_remove_first, - gl_tree_remove_last, gl_tree_remove, gl_tree_list_free, gl_tree_iterator, diff --git a/lib/gl_carray_list.c b/lib/gl_carray_list.c index fa17d48..36a8773 100644 --- a/lib/gl_carray_list.c +++ b/lib/gl_carray_list.c @@ -545,44 +545,6 @@ gl_carray_remove_at (gl_list_t list, size_t position) } static bool -gl_carray_remove_first (gl_list_t list) -{ - size_t count = list->count; - size_t i0; - - if (count == 0) - return false; - /* Here we know count > 0. */ - /* Like gl_carray_remove_at (list, 0). */ - i0 = list->offset; - if (list->base.dispose_fn != NULL) - list->base.dispose_fn (list->elements[i0]); - i0++; - list->offset = (i0 == list->allocated ? 0 : i0); - list->count = count - 1; - return true; -} - -static bool -gl_carray_remove_last (gl_list_t list) -{ - size_t count = list->count; - size_t i1; - - if (count == 0) - return false; - /* Here we know count > 0. */ - /* Like gl_carray_remove_at (list, count - 1). */ - i1 = list->offset + count - 1; - if (i1 >= list->allocated) - i1 -= list->allocated; - if (list->base.dispose_fn != NULL) - list->base.dispose_fn (list->elements[i1]); - list->count = count - 1; - return true; -} - -static bool gl_carray_remove_node (gl_list_t list, gl_list_node_t node) { size_t count = list->count; @@ -893,8 +855,6 @@ const struct gl_list_implementation gl_carray_list_implementation = gl_carray_nx_add_at, gl_carray_remove_node, gl_carray_remove_at, - gl_carray_remove_first, - gl_carray_remove_last, gl_carray_remove, gl_carray_list_free, gl_carray_iterator, diff --git a/lib/gl_linked_list.c b/lib/gl_linked_list.c index e2bf526..b1391ce 100644 --- a/lib/gl_linked_list.c +++ b/lib/gl_linked_list.c @@ -49,8 +49,6 @@ const struct gl_list_implementation gl_linked_list_implementation = gl_linked_nx_add_at, gl_linked_remove_node, gl_linked_remove_at, - gl_linked_remove_first, - gl_linked_remove_last, gl_linked_remove, gl_linked_list_free, gl_linked_iterator, diff --git a/lib/gl_linkedhash_list.c b/lib/gl_linkedhash_list.c index 5ffc0ce..7c7f999 100644 --- a/lib/gl_linkedhash_list.c +++ b/lib/gl_linkedhash_list.c @@ -97,8 +97,6 @@ const struct gl_list_implementation gl_linkedhash_list_implementation = gl_linked_nx_add_at, gl_linked_remove_node, gl_linked_remove_at, - gl_linked_remove_first, - gl_linked_remove_last, gl_linked_remove, gl_linked_list_free, gl_linked_iterator, diff --git a/lib/gl_list.h b/lib/gl_list.h index ea5018d..8094006 100644 --- a/lib/gl_list.h +++ b/lib/gl_list.h @@ -518,8 +518,6 @@ struct gl_list_implementation const void *elt); bool (*remove_node) (gl_list_t list, gl_list_node_t node); bool (*remove_at) (gl_list_t list, size_t position); - bool (*remove_first) (gl_list_t list); - bool (*remove_last) (gl_list_t list); bool (*remove_elt) (gl_list_t list, const void *elt); void (*list_free) (gl_list_t list); /* gl_list_iterator_t functions. */ @@ -762,15 +760,21 @@ gl_list_remove_at (gl_list_t list, size_t position) GL_LIST_INLINE bool gl_list_remove_first (gl_list_t list) { - return ((const struct gl_list_impl_base *) list)->vtable - ->remove_first (list); + size_t size = gl_list_size (list); + if (size > 0) + return gl_list_remove_at (list, 0); + else + return false; } GL_LIST_INLINE bool gl_list_remove_last (gl_list_t list) { - return ((const struct gl_list_impl_base *) list)->vtable - ->remove_last (list); + size_t size = gl_list_size (list); + if (size > 0) + return gl_list_remove_at (list, size - 1); + else + return false; } GL_LIST_INLINE bool diff --git a/lib/gl_rbtree_list.c b/lib/gl_rbtree_list.c index 6ae78c7..d79becf 100644 --- a/lib/gl_rbtree_list.c +++ b/lib/gl_rbtree_list.c @@ -87,8 +87,6 @@ const struct gl_list_implementation gl_rbtree_list_implementation = gl_tree_nx_add_at, gl_tree_remove_node, gl_tree_remove_at, - gl_tree_remove_first, - gl_tree_remove_last, gl_tree_remove, gl_tree_list_free, gl_tree_iterator, diff --git a/lib/gl_rbtreehash_list.c b/lib/gl_rbtreehash_list.c index b59b5f4..be2ee6f 100644 --- a/lib/gl_rbtreehash_list.c +++ b/lib/gl_rbtreehash_list.c @@ -112,8 +112,6 @@ const struct gl_list_implementation gl_rbtreehash_list_implementation = gl_tree_nx_add_at, gl_tree_remove_node, gl_tree_remove_at, - gl_tree_remove_first, - gl_tree_remove_last, gl_tree_remove, gl_tree_list_free, gl_tree_iterator, diff --git a/lib/gl_sublist.c b/lib/gl_sublist.c index 6e95c3b..e529a6b 100644 --- a/lib/gl_sublist.c +++ b/lib/gl_sublist.c @@ -259,22 +259,6 @@ gl_sublist_remove_at (gl_list_t list, size_t position) } static bool -gl_sublist_remove_first (gl_list_t list) -{ - if (list->end == list->start) - return false; - return gl_list_remove_at (list->whole, list->start); -} - -static bool -gl_sublist_remove_last (gl_list_t list) -{ - if (list->end == list->start) - return false; - return gl_list_remove_at (list->whole, list->end - 1); -} - -static bool gl_sublist_remove (gl_list_t list, const void *elt) { size_t position = @@ -440,8 +424,6 @@ static const struct gl_list_implementation gl_sublist_list_implementation = gl_sublist_nx_add_at, gl_sublist_remove_node, gl_sublist_remove_at, - gl_sublist_remove_first, - gl_sublist_remove_last, gl_sublist_remove, gl_sublist_list_free, gl_sublist_iterator, -- 2.7.4
From aaf24f107ae05afec56d797421aee7a287b051e9 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Sat, 2 May 2020 23:21:00 +0200 Subject: [PATCH 2/2] list: Add get_first, get_last, set_first, set_last operations. * lib/gl_list.h (gl_list_get_first, gl_list_get_last, gl_list_nx_set_first, gl_list_nx_set_last): New functions. * lib/gl_xlist.h (gl_list_set_first, gl_list_set_last): New functions. --- ChangeLog | 7 +++++++ lib/gl_list.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/gl_xlist.h | 20 ++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/ChangeLog b/ChangeLog index ac23544..0bf6ca0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2020-05-02 Bruno Haible <br...@clisp.org> + list: Add get_first, get_last, set_first, set_last operations. + * lib/gl_list.h (gl_list_get_first, gl_list_get_last, + gl_list_nx_set_first, gl_list_nx_set_last): New functions. + * lib/gl_xlist.h (gl_list_set_first, gl_list_set_last): New functions. + +2020-05-02 Bruno Haible <br...@clisp.org> + list: Remove redundant code for remove_first and remove_last operations. * lib/gl_list.h (struct gl_list_implementation): Remove fields remove_first, remove_last. diff --git a/lib/gl_list.h b/lib/gl_list.h index 8094006..7786092 100644 --- a/lib/gl_list.h +++ b/lib/gl_list.h @@ -74,7 +74,11 @@ extern "C" { gl_list_next_node O(1) O(1) O(log n) O(1) O(log n) gl_list_previous_node O(1) O(1) O(log n) O(1) O(log n) gl_list_get_at O(1) O(n) O(log n) O(n) O(log n) + gl_list_get_first O(1) O(1) O(log n) O(1) O(log n) + gl_list_get_last O(1) O(1) O(log n) O(1) O(log n) gl_list_set_at O(1) O(n) O(log n) O(n) O((log n)²)/O(log n) + gl_list_set_first O(1) O(1) O(log n) O(n)/O(1) O((log n)²)/O(log n) + gl_list_set_last O(1) O(1) O(log n) O(n)/O(1) O((log n)²)/O(log n) gl_list_search O(n) O(n) O(n) O(n)/O(1) O(log n)/O(1) gl_list_search_from O(n) O(n) O(n) O(n)/O(1) O((log n)²)/O(log n) gl_list_search_from_to O(n) O(n) O(n) O(n)/O(1) O((log n)²)/O(log n) @@ -210,6 +214,14 @@ extern gl_list_node_t gl_list_previous_node (gl_list_t list, gl_list_node_t node POSITION must be >= 0 and < gl_list_size (list). */ extern const void * gl_list_get_at (gl_list_t list, size_t position); +/* Returns the element at the first position in the list. + LIST must be non-empty. */ +extern const void * gl_list_get_first (gl_list_t list); + +/* Returns the element at the last position in the list. + LIST must be non-empty. */ +extern const void * gl_list_get_last (gl_list_t list); + /* Replaces the element at a given position in the list. POSITION must be >= 0 and < gl_list_size (list). Returns its node. */ @@ -224,6 +236,30 @@ extern gl_list_node_t gl_list_nx_set_at (gl_list_t list, size_t position, #endif ; +/* Replaces the element at the first position in the list. + LIST must be non-empty. + Returns its node. */ +/* declared in gl_xlist.h */ +extern gl_list_node_t gl_list_set_first (gl_list_t list, const void *elt); +/* Likewise. Returns NULL upon out-of-memory. */ +extern gl_list_node_t gl_list_nx_set_first (gl_list_t list, const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + +/* Replaces the element at the last position in the list. + LIST must be non-empty. + Returns its node. */ +/* declared in gl_xlist.h */ +extern gl_list_node_t gl_list_set_last (gl_list_t list, const void *elt); +/* Likewise. Returns NULL upon out-of-memory. */ +extern gl_list_node_t gl_list_nx_set_last (gl_list_t list, const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + /* Searches whether an element is already in the list. Returns its node if found, or NULL if not present in the list. */ extern gl_list_node_t gl_list_search (gl_list_t list, const void *elt); @@ -635,6 +671,18 @@ gl_list_get_at (gl_list_t list, size_t position) ->get_at (list, position); } +GL_LIST_INLINE const void * +gl_list_get_first (gl_list_t list) +{ + return gl_list_get_at (list, 0); +} + +GL_LIST_INLINE const void * +gl_list_get_last (gl_list_t list) +{ + return gl_list_get_at (list, gl_list_size (list) - 1); +} + GL_LIST_INLINE gl_list_node_t #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) __attribute__ ((__warn_unused_result__)) @@ -646,6 +694,24 @@ gl_list_nx_set_at (gl_list_t list, size_t position, const void *elt) } GL_LIST_INLINE gl_list_node_t +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_list_nx_set_first (gl_list_t list, const void *elt) +{ + return gl_list_nx_set_at (list, 0, elt); +} + +GL_LIST_INLINE gl_list_node_t +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_list_nx_set_last (gl_list_t list, const void *elt) +{ + return gl_list_nx_set_at (list, gl_list_size (list) - 1, elt); +} + +GL_LIST_INLINE gl_list_node_t gl_list_search (gl_list_t list, const void *elt) { size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); diff --git a/lib/gl_xlist.h b/lib/gl_xlist.h index ef6b93f..7bf9c23 100644 --- a/lib/gl_xlist.h +++ b/lib/gl_xlist.h @@ -52,6 +52,8 @@ extern void gl_list_node_set_value (gl_list_t list, gl_list_node_t node, const void *elt); extern gl_list_node_t gl_list_set_at (gl_list_t list, size_t position, const void *elt); +extern gl_list_node_t gl_list_set_first (gl_list_t list, const void *elt); +extern gl_list_node_t gl_list_set_last (gl_list_t list, const void *elt); extern gl_list_node_t gl_list_add_first (gl_list_t list, const void *elt); extern gl_list_node_t gl_list_add_last (gl_list_t list, const void *elt); extern gl_list_node_t gl_list_add_before (gl_list_t list, gl_list_node_t node, @@ -114,6 +116,24 @@ gl_list_set_at (gl_list_t list, size_t position, const void *elt) } GL_XLIST_INLINE gl_list_node_t +gl_list_set_first (gl_list_t list, const void *elt) +{ + gl_list_node_t result = gl_list_nx_set_first (list, elt); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE gl_list_node_t +gl_list_set_last (gl_list_t list, const void *elt) +{ + gl_list_node_t result = gl_list_nx_set_last (list, elt); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE gl_list_node_t gl_list_add_first (gl_list_t list, const void *elt) { gl_list_node_t result = gl_list_nx_add_first (list, elt); -- 2.7.4