+2021-04-03 Bruno Haible <bruno@clisp.org>
+
+ list: Add operations first_node, last_node.
+ Reported by Marc Nieper-Wißkirchen in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2021-04/msg00005.html>.
+ * lib/gl_list.h (gl_list_first_node, gl_list_last_node): New functions.
+ (struct gl_list_implementation): Add members first_node, last_node.
+ * lib/gl_array_list.c (gl_array_first_node, gl_array_last_node): New
+ functions.
+ (gl_array_list_implementation): Add the new operations.
+ * lib/gl_carray_list.c (gl_carray_first_node, gl_carray_last_node): New
+ functions.
+ (gl_carray_list_implementation): Add the new operations.
+ * lib/gl_anylinked_list2.h (gl_linked_first_node, gl_linked_last_node):
+ New functions.
+ * lib/gl_linked_list.c (gl_linked_list_implementation): Add the new
+ operations.
+ * lib/gl_linkedhash_list.c (gl_linkedhash_list_implementation):
+ Likewise.
+ * lib/gl_anytree_list2.h (gl_tree_first_node, gl_tree_last_node): New
+ functions.
+ * lib/gl_avltree_list.c (gl_avltree_list_implementation): Add the new
+ operations.
+ * lib/gl_avltreehash_list.c (gl_avltreehash_list_implementation):
+ Likewise.
+ * lib/gl_rbtree_list.c (gl_rbtree_list_implementation): Likewise.
+ * lib/gl_rbtreehash_list.c (gl_rbtreehash_list_implementation):
+ Likewise.
+ * lib/gl_sublist.c (gl_sublist_first_node, gl_sublist_last_node): New
+ functions.
+ (gl_sublist_list_implementation): Add the new operations.
+ * lib/gl_list.hh (class gl_List): Add member functions first_node,
+ last_node.
+ * doc/containers.texi: Update table.
+
2021-04-03 Bruno Haible <bruno@clisp.org>
xalloc-die: Fix compilation error (regression from 2021-03-28).
@tab @math{O(1)}
@tab @math{O(@log n)}
@tab @math{O(@log n)}
+@item @code{gl_list_first_node}
+@tab @math{O(1)}
+@tab @math{O(1)}
+@tab @math{O(1)}
+@tab @math{O(@log n)}
+@tab @math{O(1)}
+@tab @math{O(1)}
+@tab @math{O(@log n)}
+@tab @math{O(@log n)}
+@item @code{gl_list_last_node}
+@tab @math{O(1)}
+@tab @math{O(1)}
+@tab @math{O(1)}
+@tab @math{O(@log n)}
+@tab @math{O(1)}
+@tab @math{O(1)}
+@tab @math{O(@log n)}
+@tab @math{O(@log n)}
@item @code{gl_list_get_at}
@tab @math{O(1)}
@tab @math{O(1)}
return (node->prev != &list->root ? node->prev : NULL);
}
+static gl_list_node_t _GL_ATTRIBUTE_PURE
+gl_linked_first_node (gl_list_t list)
+{
+ if (list->count > 0)
+ return list->root.next;
+ else
+ return NULL;
+}
+
+static gl_list_node_t _GL_ATTRIBUTE_PURE
+gl_linked_last_node (gl_list_t list)
+{
+ if (list->count > 0)
+ return list->root.prev;
+ else
+ return NULL;
+}
+
static const void * _GL_ATTRIBUTE_PURE
gl_linked_get_at (gl_list_t list, size_t position)
{
return node;
}
+static gl_list_node_t _GL_ATTRIBUTE_PURE
+gl_tree_first_node (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED)
+{
+ gl_list_node_t node = list->root;
+
+ if (node != NULL)
+ {
+ while (node->left != NULL)
+ node = node->left;
+ }
+ return node;
+}
+
+static gl_list_node_t _GL_ATTRIBUTE_PURE
+gl_tree_last_node (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED)
+{
+ gl_list_node_t node = list->root;
+
+ if (node != NULL)
+ {
+ while (node->right != NULL)
+ node = node->right;
+ }
+ return node;
+}
+
/* Returns the node at the given position < gl_tree_size (list). */
static gl_list_node_t _GL_ATTRIBUTE_PURE
node_at (gl_list_node_t root, size_t position)
return NULL;
}
+static gl_list_node_t _GL_ATTRIBUTE_PURE
+gl_array_first_node (gl_list_t list)
+{
+ if (list->count > 0)
+ return INDEX_TO_NODE (0);
+ else
+ return NULL;
+}
+
+static gl_list_node_t _GL_ATTRIBUTE_PURE
+gl_array_last_node (gl_list_t list)
+{
+ if (list->count > 0)
+ return INDEX_TO_NODE (list->count - 1);
+ else
+ return NULL;
+}
+
static const void * _GL_ATTRIBUTE_PURE
gl_array_get_at (gl_list_t list, size_t position)
{
gl_array_node_nx_set_value,
gl_array_next_node,
gl_array_previous_node,
+ gl_array_first_node,
+ gl_array_last_node,
gl_array_get_at,
gl_array_nx_set_at,
gl_array_search_from_to,
gl_tree_node_nx_set_value,
gl_tree_next_node,
gl_tree_previous_node,
+ gl_tree_first_node,
+ gl_tree_last_node,
gl_tree_get_at,
gl_tree_nx_set_at,
gl_tree_search_from_to,
gl_tree_node_nx_set_value,
gl_tree_next_node,
gl_tree_previous_node,
+ gl_tree_first_node,
+ gl_tree_last_node,
gl_tree_get_at,
gl_tree_nx_set_at,
gl_tree_search_from_to,
return NULL;
}
+static gl_list_node_t _GL_ATTRIBUTE_PURE
+gl_carray_first_node (gl_list_t list)
+{
+ if (list->count > 0)
+ return INDEX_TO_NODE (0);
+ else
+ return NULL;
+}
+
+static gl_list_node_t _GL_ATTRIBUTE_PURE
+gl_carray_last_node (gl_list_t list)
+{
+ if (list->count > 0)
+ return INDEX_TO_NODE (list->count - 1);
+ else
+ return NULL;
+}
+
static const void * _GL_ATTRIBUTE_PURE
gl_carray_get_at (gl_list_t list, size_t position)
{
gl_carray_node_nx_set_value,
gl_carray_next_node,
gl_carray_previous_node,
+ gl_carray_first_node,
+ gl_carray_last_node,
gl_carray_get_at,
gl_carray_nx_set_at,
gl_carray_search_from_to,
gl_linked_node_nx_set_value,
gl_linked_next_node,
gl_linked_previous_node,
+ gl_linked_first_node,
+ gl_linked_last_node,
gl_linked_get_at,
gl_linked_nx_set_at,
gl_linked_search_from_to,
gl_linked_node_nx_set_value,
gl_linked_next_node,
gl_linked_previous_node,
+ gl_linked_first_node,
+ gl_linked_last_node,
gl_linked_get_at,
gl_linked_nx_set_at,
gl_linked_search_from_to,
gl_list_node_set_value O(1) O(1) O(1) O(1) O((log n)²)/O(1)
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_first_node O(1) O(1) O(log n) O(1) O(log n)
+ gl_list_last_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)
if the given node is the first (leftmost) one in the list. */
extern gl_list_node_t gl_list_previous_node (gl_list_t list, gl_list_node_t node);
+/* Returns the first node in the list, or NULL if the list is empty.
+ This function is useful for iterating through the list like this:
+ gl_list_node_t node;
+ for (node = gl_list_first_node (list); node != NULL; node = gl_list_next_node (node))
+ ...
+ */
+extern gl_list_node_t gl_list_first_node (gl_list_t list);
+
+/* Returns the last node in the list, or NULL if the list is empty.
+ This function is useful for iterating through the list in backward order,
+ like this:
+ gl_list_node_t node;
+ for (node = gl_list_last_node (list); node != NULL; node = gl_list_previous_node (node))
+ ...
+ */
+extern gl_list_node_t gl_list_last_node (gl_list_t list);
+
/* Returns the element at a given position in the list.
POSITION must be >= 0 and < gl_list_size (list). */
extern const void * gl_list_get_at (gl_list_t list, size_t position);
const void *elt);
gl_list_node_t (*next_node) (gl_list_t list, gl_list_node_t node);
gl_list_node_t (*previous_node) (gl_list_t list, gl_list_node_t node);
+ gl_list_node_t (*first_node) (gl_list_t list);
+ gl_list_node_t (*last_node) (gl_list_t list);
const void * (*get_at) (gl_list_t list, size_t position);
gl_list_node_t (*nx_set_at) (gl_list_t list, size_t position,
const void *elt);
->previous_node (list, node);
}
+GL_LIST_INLINE gl_list_node_t
+gl_list_first_node (gl_list_t list)
+{
+ return ((const struct gl_list_impl_base *) list)->vtable
+ ->first_node (list);
+}
+
+GL_LIST_INLINE gl_list_node_t
+gl_list_last_node (gl_list_t list)
+{
+ return ((const struct gl_list_impl_base *) list)->vtable
+ ->last_node (list);
+}
+
GL_LIST_INLINE const void *
gl_list_get_at (gl_list_t list, size_t position)
{
gl_list_node_t previous_node (gl_list_node_t node) const
{ return gl_list_previous_node (_ptr, node); }
+ /* Returns the first node in the list, or NULL if the list is empty. */
+ gl_list_node_t first_node () const
+ { return gl_list_first_node (_ptr); }
+
+ /* Returns the last node in the list, or NULL if the list is empty. */
+ gl_list_node_t last_node () const
+ { return gl_list_last_node (_ptr); }
+
/* Returns the element at a given position in the list.
POSITION must be >= 0 and < gl_list_size (list). */
ELTYPE * get_at (size_t position) const
gl_tree_node_nx_set_value,
gl_tree_next_node,
gl_tree_previous_node,
+ gl_tree_first_node,
+ gl_tree_last_node,
gl_tree_get_at,
gl_tree_nx_set_at,
gl_tree_search_from_to,
gl_tree_node_nx_set_value,
gl_tree_next_node,
gl_tree_previous_node,
+ gl_tree_first_node,
+ gl_tree_last_node,
gl_tree_get_at,
gl_tree_nx_set_at,
gl_tree_search_from_to,
return NULL;
}
+static gl_list_node_t
+gl_sublist_first_node (gl_list_t list)
+{
+ if (list->end > list->start)
+ return INDEX_TO_NODE (0);
+ else
+ return NULL;
+}
+
+static gl_list_node_t
+gl_sublist_last_node (gl_list_t list)
+{
+ size_t count = list->end - list->start;
+ if (count > 0)
+ return INDEX_TO_NODE (count - 1);
+ else
+ return NULL;
+}
+
static const void *
gl_sublist_get_at (gl_list_t list, size_t position)
{
gl_sublist_node_nx_set_value,
gl_sublist_next_node,
gl_sublist_previous_node,
+ gl_sublist_first_node,
+ gl_sublist_last_node,
gl_sublist_get_at,
gl_sublist_nx_set_at,
gl_sublist_search_from_to,