llist
- linked lists#include "llist.h"
This is the internal module for linked lists. The API is designed to be flexible but also to avoid dynamic memory allocation.
None of the involved structs should be accessed using struct fields (outside
of llist.c
). Use the functions.
struct Curl_llist
is the struct holding a single linked list. It needs to be
initialized with a call to Curl_llist_init()
before it can be used
To clean up a list, call Curl_llist_destroy()
. Since the linked lists
themselves do not allocate memory, it can also be fine to just not clean up
the list.
There are two functions for adding a node to a linked list:
Curl_llist_append
Curl_llist_insert_next
When a node is added to a list, it stores an associated custom pointer to
anything you like and you provide a pointer to a struct Curl_llist_node
struct in which it stores and updates pointers. If you intend to add the same
struct to multiple lists concurrently, you need to have one struct
Curl_llist_node
for each list.
Add a node to a list with Curl_llist_append(list, elem, node)
. Where
list
: points to a struct Curl_llist
elem
: points to what you want added to the listnode
: is a pointer to a struct Curl_llist_node
. Data storage for this
node.Example: to add a struct foobar
to a linked list. Add a node struct within
it:
struct foobar {
char *random;
struct Curl_llist_node storage; /* can be anywhere in the struct */
char *data;
};
struct Curl_llist barlist; /* the list for foobar entries */
struct foobar entries[10];
Curl_llist_init(&barlist, NULL);
/* add the first struct to the list */
Curl_llist_append(&barlist, &entries[0], &entries[0].storage);
See also Curl_llist_insert_next
.
Remove a node again from a list by calling Curl_llist_remove()
. This
will destroy the node's elem
(e.g. calling a registered free function).
To remove a node without destroying it's elem
, use
Curl_node_take_elem()
which returns the elem
pointer and
removes the node from the list. The caller then owns this pointer
and has to take care of it.
To iterate over a list: first get the head entry and then iterate over the nodes as long there is a next. Each node has an element associated with it, the custom pointer you stored there. Usually a struct pointer or similar.
struct Curl_llist_node *iter;
/* get the first entry of the 'barlist' */
iter = Curl_llist_head(&barlist);
while(iter) {
/* extract the element pointer from the node */
struct foobar *elem = Curl_node_elem(iter);
/* advance to the next node in the list */
iter = Curl_node_next(iter);
}
Curl_llist_init
void Curl_llist_init(struct Curl_llist *list, Curl_llist_dtor dtor);
Initializes the list
. The argument dtor
is NULL or a function pointer that
gets called when list nodes are removed from this list.
The function is infallible.
typedef void (*Curl_llist_dtor)(void *user, void *elem);
dtor
is called with two arguments: user
and elem
. The first being the
user
pointer passed in to Curl_llist_remove()
or Curl_llist_destroy()
and
the second is the elem
pointer associated with removed node. The pointer
that Curl_node_elem()
would have returned for that node.
Curl_llist_destroy
void Curl_llist_destroy(struct Curl_llist *list, void *user);
This removes all nodes from the list
. This leaves the list in a cleared
state.
The function is infallible.
Curl_llist_append
void Curl_llist_append(struct Curl_llist *list,
const void *elem, struct Curl_llist_node *node);
Adds node
last in the list
with a custom pointer to elem
.
The function is infallible.
Curl_llist_insert_next
void Curl_llist_insert_next(struct Curl_llist *list,
struct Curl_llist_node *node,
const void *elem,
struct Curl_llist_node *node);
Adds node
to the list
with a custom pointer to elem
immediately after
the previous list node
.
The function is infallible.
Curl_llist_head
struct Curl_llist_node *Curl_llist_head(struct Curl_llist *list);
Returns a pointer to the first node of the list
, or a NULL if empty.
Curl_node_uremove
void Curl_node_uremove(struct Curl_llist_node *node, void *user);
Removes the node
the list it was previously added to. Passes the user
pointer to the list's destructor function if one was setup.
The function is infallible.
Curl_node_remove
void Curl_node_remove(struct Curl_llist_node *node);
Removes the node
the list it was previously added to. Passes a NULL pointer
to the list's destructor function if one was setup.
The function is infallible.
Curl_node_elem
void *Curl_node_elem(struct Curl_llist_node *node);
Given a list node, this function returns the associated element.
Curl_node_next
struct Curl_llist_node *Curl_node_next(struct Curl_llist_node *node);
Given a list node, this function returns the next node in the list.